diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..dd84ea78 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.gitignore b/.gitignore index a44b8419..0e236211 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ bin gen obj -libs local.properties .DS_Store .metadata diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..84c8d6ba --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "leveldb-mcpe"] + path = leveldb/src/main/cpp/leveldb-mcpe + url = git@github.com:Mojang/leveldb-mcpe diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 6c0c5588..3b6f995e 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -2,22 +2,45 @@ # Original author -@protolambda +*Proto Lambda*\(Link removed as he asked to\) # Maintainer(s) -@protolambda +Order by joined date. + +*Proto Lambda*\(Link removed as he asked to\) (Inactive & Do Not Disturb) + +[@MithrilMania](https://github.com/MithrilMania) (Half Active) + +[@MeowCat](https://github.com/oO0oO0oO0o0o00) (Half Active) # Main contributors -... +Order by joined date. + +*Proto Lambda*\(Link removed as he asked to\) + +[@MithrilMania](https://github.com/MithrilMania) + +[@flagmaggot](https://github.com/flagmaggot) +[@MeowCat](https://github.com/oO0oO0oO0o0o00) # Contributors -... +Order by joined date. + +[@MiemieMethod](https://github.com/MiemieMethod) for Chinese translation and beta test. + +[@Manuel](https://github.com/LordJunior) for Brazilian Portuguese translation. + +*ScrapperBox25* for Indonesian translation. + +*Tcbdxh* + +And many others. diff --git a/README.md b/README.md index 2e4134e4..a5ea78ef 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,28 @@ # Blocktopograph -By @protolambda. +![author](https://github.com/Templarian/MaterialDesign/blob/master/svg/account.svg) -**NOTE**: This is a *very* old legacy project! Code quality is awful, but I'm not going to rewrite the whole app for "fun". - Feel free to fork it and improve it yourself, - it is licensed under AGPL v3; reverse engineering the MCPE format is time consuming, share your updates. +By *Proto Lambda*\(Link removed, as he asked to\), [@MithrilMania](https://github.com/MithrilMania), +[@flagmaggot](https://github.com/flagmaggot) and many other community contributors, including translation. +This fork is the only one supporting MCPE 1.13+ for now. -## [Download on Google-Play](https://play.google.com/store/apps/details?id=com.mithrilmania.blocktopograph) +## Redirection +Update is currently paused due to several difficulties (including sections below). The current active fork is now https://github.com/NguyenDuck/blocktopograph -### Showcase website +Translations and pull requests are encouraged to be made to the active forks instead of this one. -Screenshots, download links, roadmap etc. can all be found on [blocktopograph.mithrilmania.com](http://blocktopograph.mithrilmania.com). +## ![download](https://github.com/Templarian/MaterialDesign/blob/master/svg/download.svg)Download +[>>> Download on Google Play <<<](https://play.google.com/store/apps/details?id=rbq2012.blocktopograph) +[![Google Play](https://lh3.googleusercontent.com/qF9r3ZjtgG-qyHdmjecArtKiulz1gmwL_xl9R3_fzk6igSeoN0wYbJSKEX5d_fxJRwYZJpHbqcLB3i9atl-9dOfUl9an7U43TfZ9PtQ=s0)](https://play.google.com/store/apps/details?id=rbq2012.blocktopograph) +And release page of the repository provides debug version of the app. +screenshot +screenshot -## Get-started - -Steps to get started quickly: - -### Get-started: pre-installation - -This project requires you to download some android SDKs, tools, libraries and drivers. - -- SDKs + Tools: please check the sdk version before cloning a repo, then install sdk+tools for this version with SDK-manager. -- Libraries: You need to install the google-services and google-repository libraries with SDK-manager. -- Drivers: download the appropriate drivers for your phone to use `adb`. - The SDK-manager provides windows drivers for the Nexus phones. -- Some libraries are downloaded by gradle itself. You do not have to worry about these. -- Sub-modules are managed with git. (See installation) - - -### Get-started: installation - -NOTE: You may want to fork one of the dependencies (or this project) if you want to contribute. - -1. `mkdir block-project` or something like that. This will be the main-container -1. `cd` into the new folder -1. `git clone` (your fork of) this repository -1. `git clone` (your fork of) [android-leveldb](https://github.com/mithrilmania/android-leveldb) -1. `cd android-leveldb` and `git submodule update` to get the - [leveldb-mcpe](https://github.com/mithrilmania/leveldb-mcpe) git-submodule, it is required for building this project. -1. `cd ..` (back to the main container) -1. `git clone` (your fork of) [TileView](https://github.com/mithrilmania/TileView) -1. Add `local.properties` files to these projects, - with `sdk.dir` for your sdk home, - and with `ndk.dir` specified for `android-leveldb`. -1. Open the cloned blocktopograph repo with your IDE (android-studio and intellij-idea are tested). - The blocktopograph repo should be the `root-module`; - `app`, `library`(android-leveldb) and `tileview`(TileView) will be recognized as sub-modules. -1. Build the project with gradle -1. Make the project, to get android-leveldb native libs. -1. Switch build-variants of the projects you want to debug and rebuild with gradle (or leave them as is) -1. Good to go! Try running a debug build (`app` submodule)! Start with small-changes to see if you encounter any problems. +## ![build](https://github.com/Templarian/MaterialDesign/blob/master/icons/svg/camera-front-variant.svg)Build +Clone project in Android Studio: `File -> New -> Project from Version Control -> Git` +Install missing SDK components. Android Studio would give you the auto-fix options. ### Release-Workflow @@ -60,7 +31,7 @@ You can build it as debug build or sign it with your own keys. This Google-Play version will be updated after any significant and well-written feature additions and fixes. -Questions? You can reach [@protolambda on Twitter](https://twitter.com/protolambda)! +Questions? *Proto* said he does not want to be bothered about this app anymore. Issues and requests are welcome too, but please use the issue-tracker for this to keep things organized. @@ -79,14 +50,14 @@ Direct consequences: all public distributed changes in the source-code *Full license can be found in the [**LICENSE**](LICENSE) file in the root folder of this repository.* -NOTE: Please retain the attribution to @protolambda, the original author +NOTE: Please retain the attribution to *Proto Lambda*, the original author and maintainer of the official app, and later significant contributors (See [CONTRIBUTORS.md](CONTRIBUTORS.md)) out of respect for their work towards this software. LICENSE-head: Blocktopograph -- Blocktopograph is a fan-made app for MCPE, it includes a top-down world viewer and a NBT editor. - Copyright (C) 2016 @protolambda + Copyright (C) 2016 Proto Lambda This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by @@ -105,5 +76,4 @@ LICENSE-head: ## Contributing -Always welcome! Fork the project, change what you want, and send back a pull request. -Good (and properly written) features will be merged into the official app by @mithrilmania. +Always welcome! Fork the project, improve and publish! diff --git a/TODO.md b/TODO.md index 6cf97df9..5cbb713f 100644 --- a/TODO.md +++ b/TODO.md @@ -1,19 +1,3 @@ #TODO -- Translations/Localization -- MCPE 0.16 blocks + 1.0 blocks!!! -- new entities, block entities -- new icons -- unit tests -- testing! - - -#extra: - -- multithreading of the individual chunks of each tile, with a thread-pool. -- optimizing the top down rendering with lazy chunk loading (from the right direction, stopping when opaque) - -#important - -- firebase cleanup (remove config, new key) -- google big query! +- new blocks \ No newline at end of file diff --git a/_config.yml b/_config.yml new file mode 100644 index 00000000..fc24e7a6 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-hacker \ No newline at end of file diff --git a/androidx-artifact-mapping.csv b/androidx-artifact-mapping.csv new file mode 100644 index 00000000..9aeefa3f --- /dev/null +++ b/androidx-artifact-mapping.csv @@ -0,0 +1,104 @@ +Old build artifact,AndroidX build artifact +android.arch.core:common,androidx.arch.core:core-common:2.0.0-rc01 +android.arch.core:core,androidx.arch.core:core:2.0.0-rc01 +android.arch.core:core-testing,androidx.arch.core:core-testing:2.0.0-rc01 +android.arch.core:runtime,androidx.arch.core:core-runtime:2.0.0-rc01 +android.arch.lifecycle:common,androidx.lifecycle:lifecycle-common:2.0.0-rc01 +android.arch.lifecycle:common-java8,androidx.lifecycle:lifecycle-common-java8:2.0.0-rc01 +android.arch.lifecycle:compiler,androidx.lifecycle:lifecycle-compiler:2.0.0-rc01 +android.arch.lifecycle:extensions,androidx.lifecycle:lifecycle-extensions:2.0.0-rc01 +android.arch.lifecycle:livedata,androidx.lifecycle:lifecycle-livedata:2.0.0-rc01 +android.arch.lifecycle:livedata-core,androidx.lifecycle:lifecycle-livedata-core:2.0.0-rc01 +android.arch.lifecycle:reactivestreams,androidx.lifecycle:lifecycle-reactivestreams:2.0.0-rc01 +android.arch.lifecycle:runtime,androidx.lifecycle:lifecycle-runtime:2.0.0-rc01 +android.arch.lifecycle:viewmodel,androidx.lifecycle:lifecycle-viewmodel:2.0.0-rc01 +android.arch.paging:common,androidx.paging:paging-common:2.0.0-rc01 +android.arch.paging:runtime,androidx.paging:paging-runtime:2.0.0-rc01 +android.arch.paging:rxjava2,androidx.paging:paging-rxjava2:2.0.0-rc01 +android.arch.persistence.room:common,androidx.room:room-common:2.0.0-rc01 +android.arch.persistence.room:compiler,androidx.room:room-compiler:2.0.0-rc01 +android.arch.persistence.room:guava,androidx.room:room-guava:2.0.0-rc01 +android.arch.persistence.room:migration,androidx.room:room-migration:2.0.0-rc01 +android.arch.persistence.room:runtime,androidx.room:room-runtime:2.0.0-rc01 +android.arch.persistence.room:rxjava2,androidx.room:room-rxjava2:2.0.0-rc01 +android.arch.persistence.room:testing,androidx.room:room-testing:2.0.0-rc01 +android.arch.persistence:db,androidx.sqlite:sqlite:2.0.0-rc01 +android.arch.persistence:db-framework,androidx.sqlite:sqlite-framework:2.0.0-rc01 +com.android.support.constraint:constraint-layout,androidx.constraintlayout:constraintlayout:1.1.2 +com.android.support.constraint:constraint-layout-solver,androidx.constraintlayout:constraintlayout-solver:1.1.2 +com.android.support.test.espresso.idling:idling-concurrent,androidx.test.espresso.idling:idling-concurrent:3.1.0 +com.android.support.test.espresso.idling:idling-net,androidx.test.espresso.idling:idling-net:3.1.0 +com.android.support.test.espresso:espresso-accessibility,androidx.test.espresso:espresso-accessibility:3.1.0 +com.android.support.test.espresso:espresso-contrib,androidx.test.espresso:espresso-contrib:3.1.0 +com.android.support.test.espresso:espresso-core,androidx.test.espresso:espresso-core:3.1.0 +com.android.support.test.espresso:espresso-idling-resource,androidx.test.espresso:espresso-idling-resource:3.1.0 +com.android.support.test.espresso:espresso-intents,androidx.test.espresso:espresso-intents:3.1.0 +com.android.support.test.espresso:espresso-remote,androidx.test.espresso:espresso-remote:3.1.0 +com.android.support.test.espresso:espresso-web,androidx.test.espresso:espresso-web:3.1.0 +com.android.support.test.janktesthelper:janktesthelper,androidx.test.jank:janktesthelper:1.0.1 +com.android.support.test.services:test-services,androidx.test:test-services:1.1.0 +com.android.support.test.uiautomator:uiautomator,androidx.test.uiautomator:uiautomator:2.2.0 +com.android.support.test:monitor,androidx.test:monitor:1.1.0 +com.android.support.test:orchestrator,androidx.test:orchestrator:1.1.0 +com.android.support.test:rules,androidx.test:rules:1.1.0 +com.android.support.test:runner,androidx.test:runner:1.1.0 +com.android.support:animated-vector-drawable,androidx.vectordrawable:vectordrawable-animated:1.0.0 +com.android.support:appcompat-v7,androidx.appcompat:appcompat:1.0.0 +com.android.support:asynclayoutinflater,androidx.asynclayoutinflater:asynclayoutinflater:1.0.0 +com.android.support:car,androidx.car:car:1.0.0-alpha5 +com.android.support:cardview-v7,androidx.cardview:cardview:1.0.0 +com.android.support:collections,androidx.collection:collection:1.0.0 +com.android.support:coordinatorlayout,androidx.coordinatorlayout:coordinatorlayout:1.0.0 +com.android.support:cursoradapter,androidx.cursoradapter:cursoradapter:1.0.0 +com.android.support:customtabs,androidx.browser:browser:1.0.0 +com.android.support:customview,androidx.customview:customview:1.0.0 +com.android.support:design,com.google.android.material:material:1.0.0-rc01 +com.android.support:documentfile,androidx.documentfile:documentfile:1.0.0 +com.android.support:drawerlayout,androidx.drawerlayout:drawerlayout:1.0.0 +com.android.support:exifinterface,androidx.exifinterface:exifinterface:1.0.0 +com.android.support:gridlayout-v7,androidx.gridlayout:gridlayout:1.0.0 +com.android.support:heifwriter,androidx.heifwriter:heifwriter:1.0.0 +com.android.support:interpolator,androidx.interpolator:interpolator:1.0.0 +com.android.support:leanback-v17,androidx.leanback:leanback:1.0.0 +com.android.support:loader,androidx.loader:loader:1.0.0 +com.android.support:localbroadcastmanager,androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 +com.android.support:media2,androidx.media2:media2:1.0.0-alpha03 +com.android.support:media2-exoplayer,androidx.media2:media2-exoplayer:1.0.0-alpha01 +com.android.support:mediarouter-v7,androidx.mediarouter:mediarouter:1.0.0 +com.android.support:multidex,androidx.multidex:multidex:2.0.0 +com.android.support:multidex-instrumentation,androidx.multidex:multidex-instrumentation:2.0.0 +com.android.support:palette-v7,androidx.palette:palette:1.0.0 +com.android.support:percent,androidx.percentlayout:percentlayout:1.0.0 +com.android.support:preference-leanback-v17,androidx.leanback:leanback-preference:1.0.0 +com.android.support:preference-v14,androidx.legacy:legacy-preference-v14:1.0.0 +com.android.support:preference-v7,androidx.preference:preference:1.0.0 +com.android.support:print,androidx.print:print:1.0.0 +com.android.support:recommendation,androidx.recommendation:recommendation:1.0.0 +com.android.support:recyclerview-selection,androidx.recyclerview:recyclerview-selection:1.0.0 +com.android.support:recyclerview-v7,androidx.recyclerview:recyclerview:1.0.0 +com.android.support:slices-builders,androidx.slice:slice-builders:1.0.0 +com.android.support:slices-core,androidx.slice:slice-core:1.0.0 +com.android.support:slices-view,androidx.slice:slice-view:1.0.0 +com.android.support:slidingpanelayout,androidx.slidingpanelayout:slidingpanelayout:1.0.0 +com.android.support:support-annotations,androidx.annotation:annotation:1.0.0 +com.android.support:support-compat,androidx.core:core:1.0.0 +com.android.support:support-content,androidx.contentpager:contentpager:1.0.0 +com.android.support:support-core-ui,androidx.legacy:legacy-support-core-ui:1.0.0 +com.android.support:support-core-utils,androidx.legacy:legacy-support-core-utils:1.0.0 +com.android.support:support-dynamic-animation,androidx.dynamicanimation:dynamicanimation:1.0.0 +com.android.support:support-emoji,androidx.emoji:emoji:1.0.0 +com.android.support:support-emoji-appcompat,androidx.emoji:emoji-appcompat:1.0.0 +com.android.support:support-emoji-bundled,androidx.emoji:emoji-bundled:1.0.0 +com.android.support:support-fragment,androidx.fragment:fragment:1.0.0 +com.android.support:support-media-compat,androidx.media:media:1.0.0 +com.android.support:support-tv-provider,androidx.tvprovider:tvprovider:1.0.0 +com.android.support:support-v13,androidx.legacy:legacy-support-v13:1.0.0 +com.android.support:support-v4,androidx.legacy:legacy-support-v4:1.0.0 +com.android.support:support-vector-drawable,androidx.vectordrawable:vectordrawable:1.0.0 +com.android.support:swiperefreshlayout,androidx.swiperefreshlayout:swiperefreshlayout:1.0.0 +com.android.support:textclassifier,androidx.textclassifier:textclassifier:1.0.0 +com.android.support:transition,androidx.transition:transition:1.0.0 +com.android.support:versionedparcelable,androidx.versionedparcelable:versionedparcelable:1.0.0 +com.android.support:viewpager,androidx.viewpager:viewpager:1.0.0 +com.android.support:wear,androidx.wear:wear:1.0.0 +com.android.support:webkit,androidx.webkit:webkit:1.0.0 diff --git a/androidx-class-mapping.csv b/androidx-class-mapping.csv new file mode 100644 index 00000000..dd86b783 --- /dev/null +++ b/androidx-class-mapping.csv @@ -0,0 +1,1937 @@ +Support Library class,Android X class +android.arch.core.executor.AppToolkitTaskExecutor,androidx.arch.core.executor.AppToolkitTaskExecutor +android.arch.core.executor.ArchTaskExecutor,androidx.arch.core.executor.ArchTaskExecutor +android.arch.core.executor.DefaultTaskExecutor,androidx.arch.core.executor.DefaultTaskExecutor +android.arch.core.executor.JunitTaskExecutorRule,androidx.arch.core.executor.JunitTaskExecutorRule +android.arch.core.executor.TaskExecutor,androidx.arch.core.executor.TaskExecutor +android.arch.core.executor.TaskExecutorWithFakeMainThread,androidx.arch.core.executor.TaskExecutorWithFakeMainThread +android.arch.core.executor.testing.CountingTaskExecutorRule,androidx.arch.core.executor.testing.CountingTaskExecutorRule +android.arch.core.executor.testing.InstantTaskExecutorRule,androidx.arch.core.executor.testing.InstantTaskExecutorRule +android.arch.core.internal.FastSafeIterableMap,androidx.arch.core.internal.FastSafeIterableMap +android.arch.core.internal.SafeIterableMap,androidx.arch.core.internal.SafeIterableMap +android.arch.core.util.Function,androidx.arch.core.util.Function +android.arch.lifecycle.AndroidViewModel,androidx.lifecycle.AndroidViewModel +android.arch.lifecycle.ClassesInfoCache,androidx.lifecycle.ClassesInfoCache +android.arch.lifecycle.CompositeGeneratedAdaptersObserver,androidx.lifecycle.CompositeGeneratedAdaptersObserver +android.arch.lifecycle.ComputableLiveData,androidx.lifecycle.ComputableLiveData +android.arch.lifecycle.DefaultLifecycleObserver,androidx.lifecycle.DefaultLifecycleObserver +android.arch.lifecycle.Elements_extKt,androidx.lifecycle.Elements_extKt +android.arch.lifecycle.EmptyActivityLifecycleCallbacks,androidx.lifecycle.EmptyActivityLifecycleCallbacks +android.arch.lifecycle.ErrorMessages,androidx.lifecycle.ErrorMessages +android.arch.lifecycle.FullLifecycleObserver,androidx.lifecycle.FullLifecycleObserver +android.arch.lifecycle.FullLifecycleObserverAdapter,androidx.lifecycle.FullLifecycleObserverAdapter +android.arch.lifecycle.GeneratedAdapter,androidx.lifecycle.GeneratedAdapter +android.arch.lifecycle.GenericLifecycleObserver,androidx.lifecycle.GenericLifecycleObserver +android.arch.lifecycle.HolderFragment,androidx.lifecycle.HolderFragment +android.arch.lifecycle.Input_collectorKt,androidx.lifecycle.Input_collectorKt +android.arch.lifecycle.Lifecycle,androidx.lifecycle.Lifecycle +android.arch.lifecycle.LifecycleDispatcher,androidx.lifecycle.LifecycleDispatcher +android.arch.lifecycle.LifecycleObserver,androidx.lifecycle.LifecycleObserver +android.arch.lifecycle.LifecycleOwner,androidx.lifecycle.LifecycleOwner +android.arch.lifecycle.LifecycleProcessor,androidx.lifecycle.LifecycleProcessor +android.arch.lifecycle.LifecycleRegistry,androidx.lifecycle.LifecycleRegistry +android.arch.lifecycle.LifecycleRegistryOwner,androidx.lifecycle.LifecycleRegistryOwner +android.arch.lifecycle.LifecycleService,androidx.lifecycle.LifecycleService +android.arch.lifecycle.Lifecycling,androidx.lifecycle.Lifecycling +android.arch.lifecycle.LiveData,androidx.lifecycle.LiveData +android.arch.lifecycle.LiveDataReactiveStreams,androidx.lifecycle.LiveDataReactiveStreams +android.arch.lifecycle.MediatorLiveData,androidx.lifecycle.MediatorLiveData +android.arch.lifecycle.MethodCallsLogger,androidx.lifecycle.MethodCallsLogger +android.arch.lifecycle.model.AdapterClass,androidx.lifecycle.model.AdapterClass +android.arch.lifecycle.model.AdapterClassKt,androidx.lifecycle.model.AdapterClassKt +android.arch.lifecycle.model.EventMethod,androidx.lifecycle.model.EventMethod +android.arch.lifecycle.model.EventMethodCall,androidx.lifecycle.model.EventMethodCall +android.arch.lifecycle.model.InputModel,androidx.lifecycle.model.InputModel +android.arch.lifecycle.model.LifecycleObserverInfo,androidx.lifecycle.model.LifecycleObserverInfo +android.arch.lifecycle.MutableLiveData,androidx.lifecycle.MutableLiveData +android.arch.lifecycle.Observer,androidx.lifecycle.Observer +android.arch.lifecycle.ObserversCollector,androidx.lifecycle.ObserversCollector +android.arch.lifecycle.OnLifecycleEvent,androidx.lifecycle.OnLifecycleEvent +android.arch.lifecycle.ProcessLifecycleOwner,androidx.lifecycle.ProcessLifecycleOwner +android.arch.lifecycle.ProcessLifecycleOwnerInitializer,androidx.lifecycle.ProcessLifecycleOwnerInitializer +android.arch.lifecycle.ReflectiveGenericLifecycleObserver,androidx.lifecycle.ReflectiveGenericLifecycleObserver +android.arch.lifecycle.ReportFragment,androidx.lifecycle.ReportFragment +android.arch.lifecycle.ServiceLifecycleDispatcher,androidx.lifecycle.ServiceLifecycleDispatcher +android.arch.lifecycle.SingleGeneratedAdapterObserver,androidx.lifecycle.SingleGeneratedAdapterObserver +android.arch.lifecycle.TransformationKt,androidx.lifecycle.TransformationKt +android.arch.lifecycle.Transformations,androidx.lifecycle.Transformations +android.arch.lifecycle.Validator,androidx.lifecycle.Validator +android.arch.lifecycle.ViewModel,androidx.lifecycle.ViewModel +android.arch.lifecycle.ViewModelProvider,androidx.lifecycle.ViewModelProvider +android.arch.lifecycle.ViewModelProviders,androidx.lifecycle.ViewModelProviders +android.arch.lifecycle.ViewModelStore,androidx.lifecycle.ViewModelStore +android.arch.lifecycle.ViewModelStoreOwner,androidx.lifecycle.ViewModelStoreOwner +android.arch.lifecycle.ViewModelStores,androidx.lifecycle.ViewModelStores +android.arch.lifecycle.WriterKt,androidx.lifecycle.WriterKt +android.arch.paging.AsyncPagedListDiffer,androidx.paging.AsyncPagedListDiffer +android.arch.paging.ContiguousDataSource,androidx.paging.ContiguousDataSource +android.arch.paging.ContiguousPagedList,androidx.paging.ContiguousPagedList +android.arch.paging.DataSource,androidx.paging.DataSource +android.arch.paging.ItemKeyedDataSource,androidx.paging.ItemKeyedDataSource +android.arch.paging.ListDataSource,androidx.paging.ListDataSource +android.arch.paging.LivePagedListBuilder,androidx.paging.LivePagedListBuilder +android.arch.paging.LivePagedListProvider,androidx.paging.LivePagedListProvider +android.arch.paging.PagedList,androidx.paging.PagedList +android.arch.paging.PagedListAdapter,androidx.paging.PagedListAdapter +android.arch.paging.PagedStorage,androidx.paging.PagedStorage +android.arch.paging.PagedStorageDiffHelper,androidx.paging.PagedStorageDiffHelper +android.arch.paging.PageKeyedDataSource,androidx.paging.PageKeyedDataSource +android.arch.paging.PageResult,androidx.paging.PageResult +android.arch.paging.PositionalDataSource,androidx.paging.PositionalDataSource +android.arch.paging.RxPagedListBuilder,androidx.paging.RxPagedListBuilder +android.arch.paging.SnapshotPagedList,androidx.paging.SnapshotPagedList +android.arch.paging.TiledDataSource,androidx.paging.TiledDataSource +android.arch.paging.TiledPagedList,androidx.paging.TiledPagedList +android.arch.paging.WrapperItemKeyedDataSource,androidx.paging.WrapperItemKeyedDataSource +android.arch.paging.WrapperPageKeyedDataSource,androidx.paging.WrapperPageKeyedDataSource +android.arch.paging.WrapperPositionalDataSource,androidx.paging.WrapperPositionalDataSource +android.arch.persistence.db.framework.FrameworkSQLiteDatabase,androidx.sqlite.db.framework.FrameworkSQLiteDatabase +android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper,androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper +android.arch.persistence.db.framework.FrameworkSQLiteOpenHelperFactory,androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory +android.arch.persistence.db.framework.FrameworkSQLiteProgram,androidx.sqlite.db.framework.FrameworkSQLiteProgram +android.arch.persistence.db.framework.FrameworkSQLiteStatement,androidx.sqlite.db.framework.FrameworkSQLiteStatement +android.arch.persistence.db.SimpleSQLiteQuery,androidx.sqlite.db.SimpleSQLiteQuery +android.arch.persistence.db.SupportSQLiteDatabase,androidx.sqlite.db.SupportSQLiteDatabase +android.arch.persistence.db.SupportSQLiteOpenHelper,androidx.sqlite.db.SupportSQLiteOpenHelper +android.arch.persistence.db.SupportSQLiteProgram,androidx.sqlite.db.SupportSQLiteProgram +android.arch.persistence.db.SupportSQLiteQuery,androidx.sqlite.db.SupportSQLiteQuery +android.arch.persistence.db.SupportSQLiteQueryBuilder,androidx.sqlite.db.SupportSQLiteQueryBuilder +android.arch.persistence.db.SupportSQLiteStatement,androidx.sqlite.db.SupportSQLiteStatement +android.arch.persistence.room.ColumnInfo,androidx.room.ColumnInfo +android.arch.persistence.room.Dao,androidx.room.Dao +android.arch.persistence.room.Database,androidx.room.Database +android.arch.persistence.room.DatabaseConfiguration,androidx.room.DatabaseConfiguration +android.arch.persistence.room.Delete,androidx.room.Delete +android.arch.persistence.room.Embedded,androidx.room.Embedded +android.arch.persistence.room.EmptyResultSetException,androidx.room.EmptyResultSetException +android.arch.persistence.room.Entity,androidx.room.Entity +android.arch.persistence.room.EntityDeletionOrUpdateAdapter,androidx.room.EntityDeletionOrUpdateAdapter +android.arch.persistence.room.EntityInsertionAdapter,androidx.room.EntityInsertionAdapter +android.arch.persistence.room.ext.AndroidTypeNames,androidx.room.ext.AndroidTypeNames +android.arch.persistence.room.ext.ArchTypeNames,androidx.room.ext.ArchTypeNames +android.arch.persistence.room.ext.CommonTypeNames,androidx.room.ext.CommonTypeNames +android.arch.persistence.room.ext.Element_extKt,androidx.room.ext.Element_extKt +android.arch.persistence.room.ext.GuavaBaseTypeNames,androidx.room.ext.GuavaBaseTypeNames +android.arch.persistence.room.ext.GuavaUtilConcurrentTypeNames,androidx.room.ext.GuavaUtilConcurrentTypeNames +android.arch.persistence.room.ext.Javapoet_extKt,androidx.room.ext.Javapoet_extKt +android.arch.persistence.room.ext.KotlinMetadataProcessor,androidx.room.ext.KotlinMetadataProcessor +android.arch.persistence.room.ext.LifecyclesTypeNames,androidx.room.ext.LifecyclesTypeNames +android.arch.persistence.room.ext.PagingTypeNames,androidx.room.ext.PagingTypeNames +android.arch.persistence.room.ext.ReactiveStreamsTypeNames,androidx.room.ext.ReactiveStreamsTypeNames +android.arch.persistence.room.ext.RoomGuavaTypeNames,androidx.room.ext.RoomGuavaTypeNames +android.arch.persistence.room.ext.RoomRxJava2TypeNames,androidx.room.ext.RoomRxJava2TypeNames +android.arch.persistence.room.ext.RoomTypeNames,androidx.room.ext.RoomTypeNames +android.arch.persistence.room.ext.RxJava2TypeNames,androidx.room.ext.RxJava2TypeNames +android.arch.persistence.room.ext.SupportDbTypeNames,androidx.room.ext.SupportDbTypeNames +android.arch.persistence.room.ForeignKey,androidx.room.ForeignKey +android.arch.persistence.room.guava.GuavaRoom,androidx.room.guava.GuavaRoom +android.arch.persistence.room.Ignore,androidx.room.Ignore +android.arch.persistence.room.Index,androidx.room.Index +android.arch.persistence.room.Insert,androidx.room.Insert +android.arch.persistence.room.InvalidationTracker,androidx.room.InvalidationTracker +android.arch.persistence.room.log.RLog,androidx.room.log.RLog +android.arch.persistence.room.migration.bundle.BundleUtil,androidx.room.migration.bundle.BundleUtil +android.arch.persistence.room.migration.bundle.DatabaseBundle,androidx.room.migration.bundle.DatabaseBundle +android.arch.persistence.room.migration.bundle.EntityBundle,androidx.room.migration.bundle.EntityBundle +android.arch.persistence.room.migration.bundle.FieldBundle,androidx.room.migration.bundle.FieldBundle +android.arch.persistence.room.migration.bundle.ForeignKeyBundle,androidx.room.migration.bundle.ForeignKeyBundle +android.arch.persistence.room.migration.bundle.IndexBundle,androidx.room.migration.bundle.IndexBundle +android.arch.persistence.room.migration.bundle.PrimaryKeyBundle,androidx.room.migration.bundle.PrimaryKeyBundle +android.arch.persistence.room.migration.bundle.SchemaBundle,androidx.room.migration.bundle.SchemaBundle +android.arch.persistence.room.migration.bundle.SchemaEquality,androidx.room.migration.bundle.SchemaEquality +android.arch.persistence.room.migration.bundle.SchemaEqualityUtil,androidx.room.migration.bundle.SchemaEqualityUtil +android.arch.persistence.room.migration.Migration,androidx.room.migration.Migration +android.arch.persistence.room.OnConflictStrategy,androidx.room.OnConflictStrategy +android.arch.persistence.room.paging.LimitOffsetDataSource,androidx.room.paging.LimitOffsetDataSource +android.arch.persistence.room.parser.Collate,androidx.room.parser.Collate +android.arch.persistence.room.parser.ParsedQuery,androidx.room.parser.ParsedQuery +android.arch.persistence.room.parser.ParserErrors,androidx.room.parser.ParserErrors +android.arch.persistence.room.parser.QueryType,androidx.room.parser.QueryType +android.arch.persistence.room.parser.QueryVisitor,androidx.room.parser.QueryVisitor +android.arch.persistence.room.parser.Section,androidx.room.parser.Section +android.arch.persistence.room.parser.SectionType,androidx.room.parser.SectionType +android.arch.persistence.room.parser.SQLiteBaseListener,androidx.room.parser.SQLiteBaseListener +android.arch.persistence.room.parser.SQLiteBaseVisitor,androidx.room.parser.SQLiteBaseVisitor +android.arch.persistence.room.parser.SQLiteLexer,androidx.room.parser.SQLiteLexer +android.arch.persistence.room.parser.SQLiteListener,androidx.room.parser.SQLiteListener +android.arch.persistence.room.parser.SQLiteParser,androidx.room.parser.SQLiteParser +android.arch.persistence.room.parser.SQLiteVisitor,androidx.room.parser.SQLiteVisitor +android.arch.persistence.room.parser.SqlParser,androidx.room.parser.SqlParser +android.arch.persistence.room.parser.SQLTypeAffinity,androidx.room.parser.SQLTypeAffinity +android.arch.persistence.room.parser.Table,androidx.room.parser.Table +android.arch.persistence.room.preconditions.Checks,androidx.room.preconditions.Checks +android.arch.persistence.room.PrimaryKey,androidx.room.PrimaryKey +android.arch.persistence.room.processor.cache.Cache,androidx.room.processor.cache.Cache +android.arch.persistence.room.processor.Context,androidx.room.processor.Context +android.arch.persistence.room.processor.CustomConverterProcessor,androidx.room.processor.CustomConverterProcessor +android.arch.persistence.room.processor.DaoProcessor,androidx.room.processor.DaoProcessor +android.arch.persistence.room.processor.DatabaseProcessor,androidx.room.processor.DatabaseProcessor +android.arch.persistence.room.processor.DeletionMethodProcessor,androidx.room.processor.DeletionMethodProcessor +android.arch.persistence.room.processor.EntityProcessor,androidx.room.processor.EntityProcessor +android.arch.persistence.room.processor.FieldProcessor,androidx.room.processor.FieldProcessor +android.arch.persistence.room.processor.InsertionMethodProcessor,androidx.room.processor.InsertionMethodProcessor +android.arch.persistence.room.processor.OnConflictProcessor,androidx.room.processor.OnConflictProcessor +android.arch.persistence.room.processor.PojoMethodProcessor,androidx.room.processor.PojoMethodProcessor +android.arch.persistence.room.processor.PojoProcessor,androidx.room.processor.PojoProcessor +android.arch.persistence.room.processor.ProcessorErrors,androidx.room.processor.ProcessorErrors +android.arch.persistence.room.processor.QueryMethodProcessor,androidx.room.processor.QueryMethodProcessor +android.arch.persistence.room.processor.QueryParameterProcessor,androidx.room.processor.QueryParameterProcessor +android.arch.persistence.room.processor.RawQueryMethodProcessor,androidx.room.processor.RawQueryMethodProcessor +android.arch.persistence.room.processor.ShortcutMethodProcessor,androidx.room.processor.ShortcutMethodProcessor +android.arch.persistence.room.processor.ShortcutParameterProcessor,androidx.room.processor.ShortcutParameterProcessor +android.arch.persistence.room.processor.SuppressWarningProcessor,androidx.room.processor.SuppressWarningProcessor +android.arch.persistence.room.processor.TransactionMethodProcessor,androidx.room.processor.TransactionMethodProcessor +android.arch.persistence.room.processor.UpdateMethodProcessor,androidx.room.processor.UpdateMethodProcessor +android.arch.persistence.room.Query,androidx.room.Query +android.arch.persistence.room.RawQuery,androidx.room.RawQuery +android.arch.persistence.room.Relation,androidx.room.Relation +android.arch.persistence.room.Room,androidx.room.Room +android.arch.persistence.room.RoomDatabase,androidx.room.RoomDatabase +android.arch.persistence.room.RoomMasterTable,androidx.room.RoomMasterTable +android.arch.persistence.room.RoomOpenHelper,androidx.room.RoomOpenHelper +android.arch.persistence.room.RoomProcessor,androidx.room.RoomProcessor +android.arch.persistence.room.RoomSQLiteQuery,androidx.room.RoomSQLiteQuery +android.arch.persistence.room.RoomWarnings,androidx.room.RoomWarnings +android.arch.persistence.room.RxRoom,androidx.room.RxRoom +android.arch.persistence.room.SharedSQLiteStatement,androidx.room.SharedSQLiteStatement +android.arch.persistence.room.SkipQueryVerification,androidx.room.SkipQueryVerification +android.arch.persistence.room.solver.binderprovider.CursorQueryResultBinderProvider,androidx.room.solver.binderprovider.CursorQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.DataSourceFactoryQueryResultBinderProvider,androidx.room.solver.binderprovider.DataSourceFactoryQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.DataSourceQueryResultBinderProvider,androidx.room.solver.binderprovider.DataSourceQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.FlowableQueryResultBinderProvider,androidx.room.solver.binderprovider.FlowableQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.GuavaListenableFutureQueryResultBinderProvider,androidx.room.solver.binderprovider.GuavaListenableFutureQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.InstantQueryResultBinderProvider,androidx.room.solver.binderprovider.InstantQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.LiveDataQueryResultBinderProvider,androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.RxCallableQueryResultBinderProvider,androidx.room.solver.binderprovider.RxCallableQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.RxMaybeQueryResultBinderProvider,androidx.room.solver.binderprovider.RxMaybeQueryResultBinderProvider +android.arch.persistence.room.solver.binderprovider.RxSingleQueryResultBinderProvider,androidx.room.solver.binderprovider.RxSingleQueryResultBinderProvider +android.arch.persistence.room.solver.CodeGenScope,androidx.room.solver.CodeGenScope +android.arch.persistence.room.solver.ObservableQueryResultBinderProvider,androidx.room.solver.ObservableQueryResultBinderProvider +android.arch.persistence.room.solver.query.parameter.ArrayQueryParameterAdapter,androidx.room.solver.query.parameter.ArrayQueryParameterAdapter +android.arch.persistence.room.solver.query.parameter.BasicQueryParameterAdapter,androidx.room.solver.query.parameter.BasicQueryParameterAdapter +android.arch.persistence.room.solver.query.parameter.CollectionQueryParameterAdapter,androidx.room.solver.query.parameter.CollectionQueryParameterAdapter +android.arch.persistence.room.solver.query.parameter.QueryParameterAdapter,androidx.room.solver.query.parameter.QueryParameterAdapter +android.arch.persistence.room.solver.query.result.ArrayQueryResultAdapter,androidx.room.solver.query.result.ArrayQueryResultAdapter +android.arch.persistence.room.solver.query.result.BaseObservableQueryResultBinder,androidx.room.solver.query.result.BaseObservableQueryResultBinder +android.arch.persistence.room.solver.query.result.CursorQueryResultBinder,androidx.room.solver.query.result.CursorQueryResultBinder +android.arch.persistence.room.solver.query.result.DataSourceFactoryQueryResultBinder,androidx.room.solver.query.result.DataSourceFactoryQueryResultBinder +android.arch.persistence.room.solver.query.result.EntityRowAdapter,androidx.room.solver.query.result.EntityRowAdapter +android.arch.persistence.room.solver.query.result.FlowableQueryResultBinder,androidx.room.solver.query.result.FlowableQueryResultBinder +android.arch.persistence.room.solver.query.result.GuavaListenableFutureQueryResultBinder,androidx.room.solver.query.result.GuavaListenableFutureQueryResultBinder +android.arch.persistence.room.solver.query.result.GuavaOptionalQueryResultAdapter,androidx.room.solver.query.result.GuavaOptionalQueryResultAdapter +android.arch.persistence.room.solver.query.result.InstantQueryResultBinder,androidx.room.solver.query.result.InstantQueryResultBinder +android.arch.persistence.room.solver.query.result.ListQueryResultAdapter,androidx.room.solver.query.result.ListQueryResultAdapter +android.arch.persistence.room.solver.query.result.LiveDataQueryResultBinder,androidx.room.solver.query.result.LiveDataQueryResultBinder +android.arch.persistence.room.solver.query.result.OptionalQueryResultAdapter,androidx.room.solver.query.result.OptionalQueryResultAdapter +android.arch.persistence.room.solver.query.result.PojoRowAdapter,androidx.room.solver.query.result.PojoRowAdapter +android.arch.persistence.room.solver.query.result.PositionalDataSourceQueryResultBinder,androidx.room.solver.query.result.PositionalDataSourceQueryResultBinder +android.arch.persistence.room.solver.query.result.QueryResultAdapter,androidx.room.solver.query.result.QueryResultAdapter +android.arch.persistence.room.solver.query.result.QueryResultBinder,androidx.room.solver.query.result.QueryResultBinder +android.arch.persistence.room.solver.query.result.RowAdapter,androidx.room.solver.query.result.RowAdapter +android.arch.persistence.room.solver.query.result.RxCallableQueryResultBinder,androidx.room.solver.query.result.RxCallableQueryResultBinder +android.arch.persistence.room.solver.query.result.SingleColumnRowAdapter,androidx.room.solver.query.result.SingleColumnRowAdapter +android.arch.persistence.room.solver.query.result.SingleEntityQueryResultAdapter,androidx.room.solver.query.result.SingleEntityQueryResultAdapter +android.arch.persistence.room.solver.query.result.TransactionWrapper,androidx.room.solver.query.result.TransactionWrapper +android.arch.persistence.room.solver.query.result.TransactionWrapperKt,androidx.room.solver.query.result.TransactionWrapperKt +android.arch.persistence.room.solver.QueryResultBinderProvider,androidx.room.solver.QueryResultBinderProvider +android.arch.persistence.room.solver.TypeAdapterStore,androidx.room.solver.TypeAdapterStore +android.arch.persistence.room.solver.types.BoxedBooleanToBoxedIntConverter,androidx.room.solver.types.BoxedBooleanToBoxedIntConverter +android.arch.persistence.room.solver.types.BoxedPrimitiveColumnTypeAdapter,androidx.room.solver.types.BoxedPrimitiveColumnTypeAdapter +android.arch.persistence.room.solver.types.ByteArrayColumnTypeAdapter,androidx.room.solver.types.ByteArrayColumnTypeAdapter +android.arch.persistence.room.solver.types.ColumnTypeAdapter,androidx.room.solver.types.ColumnTypeAdapter +android.arch.persistence.room.solver.types.CompositeAdapter,androidx.room.solver.types.CompositeAdapter +android.arch.persistence.room.solver.types.CompositeTypeConverter,androidx.room.solver.types.CompositeTypeConverter +android.arch.persistence.room.solver.types.CursorValueReader,androidx.room.solver.types.CursorValueReader +android.arch.persistence.room.solver.types.CustomTypeConverterWrapper,androidx.room.solver.types.CustomTypeConverterWrapper +android.arch.persistence.room.solver.types.NoOpConverter,androidx.room.solver.types.NoOpConverter +android.arch.persistence.room.solver.types.PrimitiveBooleanToIntConverter,androidx.room.solver.types.PrimitiveBooleanToIntConverter +android.arch.persistence.room.solver.types.PrimitiveColumnTypeAdapter,androidx.room.solver.types.PrimitiveColumnTypeAdapter +android.arch.persistence.room.solver.types.StatementValueBinder,androidx.room.solver.types.StatementValueBinder +android.arch.persistence.room.solver.types.StringColumnTypeAdapter,androidx.room.solver.types.StringColumnTypeAdapter +android.arch.persistence.room.solver.types.TypeConverter,androidx.room.solver.types.TypeConverter +android.arch.persistence.room.testing.MigrationTestHelper,androidx.room.testing.MigrationTestHelper +android.arch.persistence.room.Transaction,androidx.room.Transaction +android.arch.persistence.room.TypeConverter,androidx.room.TypeConverter +android.arch.persistence.room.TypeConverters,androidx.room.TypeConverters +android.arch.persistence.room.Update,androidx.room.Update +android.arch.persistence.room.util.StringUtil,androidx.room.util.StringUtil +android.arch.persistence.room.util.TableInfo,androidx.room.util.TableInfo +android.arch.persistence.room.verifier.ColumnInfo,androidx.room.verifier.ColumnInfo +android.arch.persistence.room.verifier.DatabaseVerificaitonErrors,androidx.room.verifier.DatabaseVerificaitonErrors +android.arch.persistence.room.verifier.DatabaseVerifier,androidx.room.verifier.DatabaseVerifier +android.arch.persistence.room.verifier.QueryResultInfo,androidx.room.verifier.QueryResultInfo +android.arch.persistence.room.vo.CallType,androidx.room.vo.CallType +android.arch.persistence.room.vo.Constructor,androidx.room.vo.Constructor +android.arch.persistence.room.vo.CustomTypeConverter,androidx.room.vo.CustomTypeConverter +android.arch.persistence.room.vo.Dao,androidx.room.vo.Dao +android.arch.persistence.room.vo.DaoMethod,androidx.room.vo.DaoMethod +android.arch.persistence.room.vo.Database,androidx.room.vo.Database +android.arch.persistence.room.vo.DeletionMethod,androidx.room.vo.DeletionMethod +android.arch.persistence.room.vo.EmbeddedField,androidx.room.vo.EmbeddedField +android.arch.persistence.room.vo.Entity,androidx.room.vo.Entity +android.arch.persistence.room.vo.Field,androidx.room.vo.Field +android.arch.persistence.room.vo.FieldGetter,androidx.room.vo.FieldGetter +android.arch.persistence.room.vo.FieldSetter,androidx.room.vo.FieldSetter +android.arch.persistence.room.vo.FieldWithIndex,androidx.room.vo.FieldWithIndex +android.arch.persistence.room.vo.ForeignKey,androidx.room.vo.ForeignKey +android.arch.persistence.room.vo.ForeignKeyAction,androidx.room.vo.ForeignKeyAction +android.arch.persistence.room.vo.HasSchemaIdentity,androidx.room.vo.HasSchemaIdentity +android.arch.persistence.room.vo.Index,androidx.room.vo.Index +android.arch.persistence.room.vo.InsertionMethod,androidx.room.vo.InsertionMethod +android.arch.persistence.room.vo.Pojo,androidx.room.vo.Pojo +android.arch.persistence.room.vo.PojoMethod,androidx.room.vo.PojoMethod +android.arch.persistence.room.vo.PrimaryKey,androidx.room.vo.PrimaryKey +android.arch.persistence.room.vo.QueryMethod,androidx.room.vo.QueryMethod +android.arch.persistence.room.vo.QueryParameter,androidx.room.vo.QueryParameter +android.arch.persistence.room.vo.RawQueryMethod,androidx.room.vo.RawQueryMethod +android.arch.persistence.room.vo.Relation,androidx.room.vo.Relation +android.arch.persistence.room.vo.RelationCollector,androidx.room.vo.RelationCollector +android.arch.persistence.room.vo.SchemaIdentityKey,androidx.room.vo.SchemaIdentityKey +android.arch.persistence.room.vo.ShortcutMethod,androidx.room.vo.ShortcutMethod +android.arch.persistence.room.vo.ShortcutQueryParameter,androidx.room.vo.ShortcutQueryParameter +android.arch.persistence.room.vo.TransactionMethod,androidx.room.vo.TransactionMethod +android.arch.persistence.room.vo.UpdateMethod,androidx.room.vo.UpdateMethod +android.arch.persistence.room.vo.Warning,androidx.room.vo.Warning +android.arch.persistence.room.writer.ClassWriter,androidx.room.writer.ClassWriter +android.arch.persistence.room.writer.DaoWriter,androidx.room.writer.DaoWriter +android.arch.persistence.room.writer.DatabaseWriter,androidx.room.writer.DatabaseWriter +android.arch.persistence.room.writer.EntityCursorConverterWriter,androidx.room.writer.EntityCursorConverterWriter +android.arch.persistence.room.writer.EntityDeleteComparator,androidx.room.writer.EntityDeleteComparator +android.arch.persistence.room.writer.EntityDeletionAdapterWriter,androidx.room.writer.EntityDeletionAdapterWriter +android.arch.persistence.room.writer.EntityInsertionAdapterWriter,androidx.room.writer.EntityInsertionAdapterWriter +android.arch.persistence.room.writer.EntityUpdateAdapterWriter,androidx.room.writer.EntityUpdateAdapterWriter +android.arch.persistence.room.writer.FieldReadWriteWriter,androidx.room.writer.FieldReadWriteWriter +android.arch.persistence.room.writer.PreparedStatementWriter,androidx.room.writer.PreparedStatementWriter +android.arch.persistence.room.writer.QueryWriter,androidx.room.writer.QueryWriter +android.arch.persistence.room.writer.RelationCollectorMethodWriter,androidx.room.writer.RelationCollectorMethodWriter +android.arch.persistence.room.writer.SQLiteOpenHelperWriter,androidx.room.writer.SQLiteOpenHelperWriter +android.arch.persistence.room.writer.TableInfoValidationWriter,androidx.room.writer.TableInfoValidationWriter +android.databinding.adapters.AbsListViewBindingAdapter,androidx.databinding.adapters.AbsListViewBindingAdapter +android.databinding.adapters.AbsSeekBarBindingAdapter,androidx.databinding.adapters.AbsSeekBarBindingAdapter +android.databinding.adapters.AbsSpinnerBindingAdapter,androidx.databinding.adapters.AbsSpinnerBindingAdapter +android.databinding.adapters.ActionMenuViewBindingAdapter,androidx.databinding.adapters.ActionMenuViewBindingAdapter +android.databinding.adapters.AdapterViewBindingAdapter,androidx.databinding.adapters.AdapterViewBindingAdapter +android.databinding.adapters.AutoCompleteTextViewBindingAdapter,androidx.databinding.adapters.AutoCompleteTextViewBindingAdapter +android.databinding.adapters.CalendarViewBindingAdapter,androidx.databinding.adapters.CalendarViewBindingAdapter +android.databinding.adapters.CardViewBindingAdapter,androidx.databinding.adapters.CardViewBindingAdapter +android.databinding.adapters.CheckedTextViewBindingAdapter,androidx.databinding.adapters.CheckedTextViewBindingAdapter +android.databinding.adapters.ChronometerBindingAdapter,androidx.databinding.adapters.ChronometerBindingAdapter +android.databinding.adapters.CompoundButtonBindingAdapter,androidx.databinding.adapters.CompoundButtonBindingAdapter +android.databinding.adapters.Converters,androidx.databinding.adapters.Converters +android.databinding.adapters.DatePickerBindingAdapter,androidx.databinding.adapters.DatePickerBindingAdapter +android.databinding.adapters.ExpandableListViewBindingAdapter,androidx.databinding.adapters.ExpandableListViewBindingAdapter +android.databinding.adapters.FrameLayoutBindingAdapter,androidx.databinding.adapters.FrameLayoutBindingAdapter +android.databinding.adapters.ImageViewBindingAdapter,androidx.databinding.adapters.ImageViewBindingAdapter +android.databinding.adapters.LinearLayoutBindingAdapter,androidx.databinding.adapters.LinearLayoutBindingAdapter +android.databinding.adapters.ListenerUtil,androidx.databinding.adapters.ListenerUtil +android.databinding.adapters.NumberPickerBindingAdapter,androidx.databinding.adapters.NumberPickerBindingAdapter +android.databinding.adapters.ObservableListAdapter,androidx.databinding.adapters.ObservableListAdapter +android.databinding.adapters.ProgressBarBindingAdapter,androidx.databinding.adapters.ProgressBarBindingAdapter +android.databinding.adapters.RadioGroupBindingAdapter,androidx.databinding.adapters.RadioGroupBindingAdapter +android.databinding.adapters.RatingBarBindingAdapter,androidx.databinding.adapters.RatingBarBindingAdapter +android.databinding.adapters.SearchViewBindingAdapter,androidx.databinding.adapters.SearchViewBindingAdapter +android.databinding.adapters.SeekBarBindingAdapter,androidx.databinding.adapters.SeekBarBindingAdapter +android.databinding.adapters.SpinnerBindingAdapter,androidx.databinding.adapters.SpinnerBindingAdapter +android.databinding.adapters.SwitchBindingAdapter,androidx.databinding.adapters.SwitchBindingAdapter +android.databinding.adapters.SwitchCompatBindingAdapter,androidx.databinding.adapters.SwitchCompatBindingAdapter +android.databinding.adapters.TabHostBindingAdapter,androidx.databinding.adapters.TabHostBindingAdapter +android.databinding.adapters.TableLayoutBindingAdapter,androidx.databinding.adapters.TableLayoutBindingAdapter +android.databinding.adapters.TabWidgetBindingAdapter,androidx.databinding.adapters.TabWidgetBindingAdapter +android.databinding.adapters.TextViewBindingAdapter,androidx.databinding.adapters.TextViewBindingAdapter +android.databinding.adapters.TimePickerBindingAdapter,androidx.databinding.adapters.TimePickerBindingAdapter +android.databinding.adapters.ToolbarBindingAdapter,androidx.databinding.adapters.ToolbarBindingAdapter +android.databinding.adapters.VideoViewBindingAdapter,androidx.databinding.adapters.VideoViewBindingAdapter +android.databinding.adapters.ViewBindingAdapter,androidx.databinding.adapters.ViewBindingAdapter +android.databinding.adapters.ViewGroupBindingAdapter,androidx.databinding.adapters.ViewGroupBindingAdapter +android.databinding.adapters.ViewStubBindingAdapter,androidx.databinding.adapters.ViewStubBindingAdapter +android.databinding.adapters.ZoomControlsBindingAdapter,androidx.databinding.adapters.ZoomControlsBindingAdapter +android.databinding.BaseObservable,androidx.databinding.BaseObservable +android.databinding.BaseObservableField,androidx.databinding.BaseObservableField +android.databinding.Bindable,androidx.databinding.Bindable +android.databinding.BindingAdapter,androidx.databinding.BindingAdapter +android.databinding.BindingBuildInfo,androidx.databinding.BindingBuildInfo +android.databinding.BindingConversion,androidx.databinding.BindingConversion +android.databinding.BindingMethod,androidx.databinding.BindingMethod +android.databinding.BindingMethods,androidx.databinding.BindingMethods +android.databinding.CallbackRegistry,androidx.databinding.CallbackRegistry +android.databinding.DataBinderMapper,androidx.databinding.DataBinderMapper +android.databinding.DataBinderMapperImpl,androidx.databinding.DataBinderMapperImpl +android.databinding.DataBindingComponent,androidx.databinding.DataBindingComponent +android.databinding.DataBindingUtil,androidx.databinding.DataBindingUtil +android.databinding.InverseBindingAdapter,androidx.databinding.InverseBindingAdapter +android.databinding.InverseBindingListener,androidx.databinding.InverseBindingListener +android.databinding.InverseBindingMethod,androidx.databinding.InverseBindingMethod +android.databinding.InverseBindingMethods,androidx.databinding.InverseBindingMethods +android.databinding.InverseMethod,androidx.databinding.InverseMethod +android.databinding.ListChangeRegistry,androidx.databinding.ListChangeRegistry +android.databinding.MapChangeRegistry,androidx.databinding.MapChangeRegistry +android.databinding.MergedDataBinderMapper,androidx.databinding.MergedDataBinderMapper +android.databinding.Observable,androidx.databinding.Observable +android.databinding.ObservableArrayList,androidx.databinding.ObservableArrayList +android.databinding.ObservableArrayMap,androidx.databinding.ObservableArrayMap +android.databinding.ObservableBoolean,androidx.databinding.ObservableBoolean +android.databinding.ObservableByte,androidx.databinding.ObservableByte +android.databinding.ObservableChar,androidx.databinding.ObservableChar +android.databinding.ObservableDouble,androidx.databinding.ObservableDouble +android.databinding.ObservableField,androidx.databinding.ObservableField +android.databinding.ObservableFloat,androidx.databinding.ObservableFloat +android.databinding.ObservableInt,androidx.databinding.ObservableInt +android.databinding.ObservableList,androidx.databinding.ObservableList +android.databinding.ObservableLong,androidx.databinding.ObservableLong +android.databinding.ObservableMap,androidx.databinding.ObservableMap +android.databinding.ObservableParcelable,androidx.databinding.ObservableParcelable +android.databinding.ObservableShort,androidx.databinding.ObservableShort +android.databinding.OnRebindCallback,androidx.databinding.OnRebindCallback +android.databinding.PropertyChangeRegistry,androidx.databinding.PropertyChangeRegistry +android.databinding.Untaggable,androidx.databinding.Untaggable +android.databinding.ViewDataBinding,androidx.databinding.ViewDataBinding +android.databinding.ViewStubProxy,androidx.databinding.ViewStubProxy +android.support.animation.AnimationHandler,androidx.dynamicanimation.animation.AnimationHandler +android.support.animation.DynamicAnimation,androidx.dynamicanimation.animation.DynamicAnimation +android.support.animation.FlingAnimation,androidx.dynamicanimation.animation.FlingAnimation +android.support.animation.FloatPropertyCompat,androidx.dynamicanimation.animation.FloatPropertyCompat +android.support.animation.FloatValueHolder,androidx.dynamicanimation.animation.FloatValueHolder +android.support.animation.Force,androidx.dynamicanimation.animation.Force +android.support.animation.SpringAnimation,androidx.dynamicanimation.animation.SpringAnimation +android.support.animation.SpringForce,androidx.dynamicanimation.animation.SpringForce +android.support.annotation.AnimatorRes,androidx.annotation.AnimatorRes +android.support.annotation.AnimRes,androidx.annotation.AnimRes +android.support.annotation.AnyRes,androidx.annotation.AnyRes +android.support.annotation.AnyThread,androidx.annotation.AnyThread +android.support.annotation.ArrayRes,androidx.annotation.ArrayRes +android.support.annotation.AttrRes,androidx.annotation.AttrRes +android.support.annotation.BinderThread,androidx.annotation.BinderThread +android.support.annotation.BoolRes,androidx.annotation.BoolRes +android.support.annotation.CallSuper,androidx.annotation.CallSuper +android.support.annotation.CheckResult,androidx.annotation.CheckResult +android.support.annotation.ColorInt,androidx.annotation.ColorInt +android.support.annotation.ColorLong,androidx.annotation.ColorLong +android.support.annotation.ColorRes,androidx.annotation.ColorRes +android.support.annotation.DimenRes,androidx.annotation.DimenRes +android.support.annotation.Dimension,androidx.annotation.Dimension +android.support.annotation.DrawableRes,androidx.annotation.DrawableRes +android.support.annotation.FloatRange,androidx.annotation.FloatRange +android.support.annotation.FontRes,androidx.annotation.FontRes +android.support.annotation.FractionRes,androidx.annotation.FractionRes +android.support.annotation.GuardedBy,androidx.annotation.GuardedBy +android.support.annotation.HalfFloat,androidx.annotation.HalfFloat +android.support.annotation.IdRes,androidx.annotation.IdRes +android.support.annotation.IntDef,androidx.annotation.IntDef +android.support.annotation.IntegerRes,androidx.annotation.IntegerRes +android.support.annotation.InterpolatorRes,androidx.annotation.InterpolatorRes +android.support.annotation.IntRange,androidx.annotation.IntRange +android.support.annotation.Keep,androidx.annotation.Keep +android.support.annotation.LayoutRes,androidx.annotation.LayoutRes +android.support.annotation.LongDef,androidx.annotation.LongDef +android.support.annotation.MainThread,androidx.annotation.MainThread +android.support.annotation.MenuRes,androidx.annotation.MenuRes +android.support.annotation.NavigationRes,androidx.annotation.NavigationRes +android.support.annotation.NonNull,androidx.annotation.NonNull +android.support.annotation.Nullable,androidx.annotation.Nullable +android.support.annotation.PluralsRes,androidx.annotation.PluralsRes +android.support.annotation.Px,androidx.annotation.Px +android.support.annotation.RawRes,androidx.annotation.RawRes +android.support.annotation.RequiresApi,androidx.annotation.RequiresApi +android.support.annotation.RequiresFeature,androidx.annotation.RequiresFeature +android.support.annotation.RequiresPermission,androidx.annotation.RequiresPermission +android.support.annotation.RestrictTo,androidx.annotation.RestrictTo +android.support.annotation.Size,androidx.annotation.Size +android.support.annotation.StringDef,androidx.annotation.StringDef +android.support.annotation.StringRes,androidx.annotation.StringRes +android.support.annotation.StyleableRes,androidx.annotation.StyleableRes +android.support.annotation.StyleRes,androidx.annotation.StyleRes +android.support.annotation.TransitionRes,androidx.annotation.TransitionRes +android.support.annotation.UiThread,androidx.annotation.UiThread +android.support.annotation.VisibleForTesting,androidx.annotation.VisibleForTesting +android.support.annotation.WorkerThread,androidx.annotation.WorkerThread +android.support.annotation.XmlRes,androidx.annotation.XmlRes +android.support.app.recommendation.ContentRecommendation,androidx.recommendation.app.ContentRecommendation +android.support.app.recommendation.RecommendationExtender,androidx.recommendation.app.RecommendationExtender +android.support.compat.R,androidx.core.R +android.support.constraint.Barrier,androidx.constraintlayout.widget.Barrier +android.support.constraint.ConstraintHelper,androidx.constraintlayout.widget.ConstraintHelper +android.support.constraint.ConstraintLayout,androidx.constraintlayout.widget.ConstraintLayout +android.support.constraint.Constraints,androidx.constraintlayout.widget.Constraints +android.support.constraint.ConstraintSet,androidx.constraintlayout.widget.ConstraintSet +android.support.constraint.Group,androidx.constraintlayout.widget.Group +android.support.constraint.Guideline,androidx.constraintlayout.widget.Guideline +android.support.constraint.Placeholder,androidx.constraintlayout.widget.Placeholder +android.support.constraint.R,androidx.constraintlayout.widget.R +android.support.constraint.solver.ArrayLinkedVariables,androidx.constraintlayout.solver.ArrayLinkedVariables +android.support.constraint.solver.ArrayRow,androidx.constraintlayout.solver.ArrayRow +android.support.constraint.solver.Cache,androidx.constraintlayout.solver.Cache +android.support.constraint.solver.GoalRow,androidx.constraintlayout.solver.GoalRow +android.support.constraint.solver.LinearSystem,androidx.constraintlayout.solver.LinearSystem +android.support.constraint.solver.Metrics,androidx.constraintlayout.solver.Metrics +android.support.constraint.solver.Pools,androidx.constraintlayout.solver.Pools +android.support.constraint.solver.SolverVariable,androidx.constraintlayout.solver.SolverVariable +android.support.constraint.solver.widgets.Analyzer,androidx.constraintlayout.solver.widgets.Analyzer +android.support.constraint.solver.widgets.Barrier,androidx.constraintlayout.solver.widgets.Barrier +android.support.constraint.solver.widgets.Chain,androidx.constraintlayout.solver.widgets.Chain +android.support.constraint.solver.widgets.ChainHead,androidx.constraintlayout.solver.widgets.ChainHead +android.support.constraint.solver.widgets.ConstraintAnchor,androidx.constraintlayout.solver.widgets.ConstraintAnchor +android.support.constraint.solver.widgets.ConstraintHorizontalLayout,androidx.constraintlayout.solver.widgets.ConstraintHorizontalLayout +android.support.constraint.solver.widgets.ConstraintTableLayout,androidx.constraintlayout.solver.widgets.ConstraintTableLayout +android.support.constraint.solver.widgets.ConstraintWidget,androidx.constraintlayout.solver.widgets.ConstraintWidget +android.support.constraint.solver.widgets.ConstraintWidgetContainer,androidx.constraintlayout.solver.widgets.ConstraintWidgetContainer +android.support.constraint.solver.widgets.ConstraintWidgetGroup,androidx.constraintlayout.solver.widgets.ConstraintWidgetGroup +android.support.constraint.solver.widgets.Guideline,androidx.constraintlayout.solver.widgets.Guideline +android.support.constraint.solver.widgets.Helper,androidx.constraintlayout.solver.widgets.Helper +android.support.constraint.solver.widgets.Optimizer,androidx.constraintlayout.solver.widgets.Optimizer +android.support.constraint.solver.widgets.Rectangle,androidx.constraintlayout.solver.widgets.Rectangle +android.support.constraint.solver.widgets.ResolutionAnchor,androidx.constraintlayout.solver.widgets.ResolutionAnchor +android.support.constraint.solver.widgets.ResolutionDimension,androidx.constraintlayout.solver.widgets.ResolutionDimension +android.support.constraint.solver.widgets.ResolutionNode,androidx.constraintlayout.solver.widgets.ResolutionNode +android.support.constraint.solver.widgets.Snapshot,androidx.constraintlayout.solver.widgets.Snapshot +android.support.constraint.solver.widgets.WidgetContainer,androidx.constraintlayout.solver.widgets.WidgetContainer +android.support.content.ContentPager,androidx.contentpager.content.ContentPager +android.support.content.InMemoryCursor,androidx.contentpager.content.InMemoryCursor +android.support.content.LoaderQueryRunner,androidx.contentpager.content.LoaderQueryRunner +android.support.content.Query,androidx.contentpager.content.Query +android.support.coordinatorlayout.R,androidx.coordinatorlayout.R +android.support.customtabs.CustomTabsCallback,androidx.browser.customtabs.CustomTabsCallback +android.support.customtabs.CustomTabsClient,androidx.browser.customtabs.CustomTabsClient +android.support.customtabs.CustomTabsIntent,androidx.browser.customtabs.CustomTabsIntent +android.support.customtabs.CustomTabsService,androidx.browser.customtabs.CustomTabsService +android.support.customtabs.CustomTabsServiceConnection,androidx.browser.customtabs.CustomTabsServiceConnection +android.support.customtabs.CustomTabsSession,androidx.browser.customtabs.CustomTabsSession +android.support.customtabs.CustomTabsSessionToken,androidx.browser.customtabs.CustomTabsSessionToken +android.support.customtabs.ICustomTabsCallback,android.support.customtabs.ICustomTabsCallback +android.support.customtabs.ICustomTabsService,android.support.customtabs.ICustomTabsService +android.support.customtabs.IPostMessageService,android.support.customtabs.IPostMessageService +android.support.customtabs.PostMessageService,androidx.browser.customtabs.PostMessageService +android.support.customtabs.PostMessageServiceConnection,androidx.browser.customtabs.PostMessageServiceConnection +android.support.customtabs.R,androidx.browser.R +android.support.customtabs.TrustedWebUtils,androidx.browser.customtabs.TrustedWebUtils +android.support.design.animation.AnimationUtils,com.google.android.material.animation.AnimationUtils +android.support.design.animation.AnimatorSetCompat,com.google.android.material.animation.AnimatorSetCompat +android.support.design.animation.ArgbEvaluatorCompat,com.google.android.material.animation.ArgbEvaluatorCompat +android.support.design.animation.ChildrenAlphaProperty,com.google.android.material.animation.ChildrenAlphaProperty +android.support.design.animation.DrawableAlphaProperty,com.google.android.material.animation.DrawableAlphaProperty +android.support.design.animation.ImageMatrixProperty,com.google.android.material.animation.ImageMatrixProperty +android.support.design.animation.MatrixEvaluator,com.google.android.material.animation.MatrixEvaluator +android.support.design.animation.MotionSpec,com.google.android.material.animation.MotionSpec +android.support.design.animation.MotionTiming,com.google.android.material.animation.MotionTiming +android.support.design.animation.Positioning,com.google.android.material.animation.Positioning +android.support.design.behavior.HideBottomViewOnScrollBehavior,com.google.android.material.behavior.HideBottomViewOnScrollBehavior +android.support.design.bottomappbar.BottomAppBar,com.google.android.material.bottomappbar.BottomAppBar +android.support.design.bottomappbar.BottomAppBarTopEdgeTreatment,com.google.android.material.bottomappbar.BottomAppBarTopEdgeTreatment +android.support.design.bottomnavigation.LabelVisibilityMode,com.google.android.material.bottomnavigation.LabelVisibilityMode +android.support.design.button.MaterialButton,com.google.android.material.button.MaterialButton +android.support.design.button.MaterialButtonBackgroundDrawable,com.google.android.material.button.MaterialButtonBackgroundDrawable +android.support.design.button.MaterialButtonHelper,com.google.android.material.button.MaterialButtonHelper +android.support.design.canvas.CanvasCompat,com.google.android.material.canvas.CanvasCompat +android.support.design.card.MaterialCardView,com.google.android.material.card.MaterialCardView +android.support.design.card.MaterialCardViewHelper,com.google.android.material.card.MaterialCardViewHelper +android.support.design.chip.Chip,com.google.android.material.chip.Chip +android.support.design.chip.ChipDrawable,com.google.android.material.chip.ChipDrawable +android.support.design.chip.ChipGroup,com.google.android.material.chip.ChipGroup +android.support.design.circularreveal.cardview.CircularRevealCardView,com.google.android.material.circularreveal.cardview.CircularRevealCardView +android.support.design.circularreveal.CircularRevealCompat,com.google.android.material.circularreveal.CircularRevealCompat +android.support.design.circularreveal.CircularRevealFrameLayout,com.google.android.material.circularreveal.CircularRevealFrameLayout +android.support.design.circularreveal.CircularRevealGridLayout,com.google.android.material.circularreveal.CircularRevealGridLayout +android.support.design.circularreveal.CircularRevealHelper,com.google.android.material.circularreveal.CircularRevealHelper +android.support.design.circularreveal.CircularRevealLinearLayout,com.google.android.material.circularreveal.CircularRevealLinearLayout +android.support.design.circularreveal.CircularRevealRelativeLayout,com.google.android.material.circularreveal.CircularRevealRelativeLayout +android.support.design.circularreveal.CircularRevealWidget,com.google.android.material.circularreveal.CircularRevealWidget +android.support.design.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout,com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout +android.support.design.drawable.DrawableUtils,com.google.android.material.drawable.DrawableUtils +android.support.design.expandable.ExpandableTransformationWidget,com.google.android.material.expandable.ExpandableTransformationWidget +android.support.design.expandable.ExpandableWidget,com.google.android.material.expandable.ExpandableWidget +android.support.design.expandable.ExpandableWidgetHelper,com.google.android.material.expandable.ExpandableWidgetHelper +android.support.design.internal.BaselineLayout,com.google.android.material.internal.BaselineLayout +android.support.design.internal.BottomNavigationItemView,com.google.android.material.bottomnavigation.BottomNavigationItemView +android.support.design.internal.BottomNavigationMenu,com.google.android.material.bottomnavigation.BottomNavigationMenu +android.support.design.internal.BottomNavigationMenuView,com.google.android.material.bottomnavigation.BottomNavigationMenuView +android.support.design.internal.BottomNavigationPresenter,com.google.android.material.bottomnavigation.BottomNavigationPresenter +android.support.design.internal.Experimental,com.google.android.material.internal.Experimental +android.support.design.internal.FlowLayout,com.google.android.material.internal.FlowLayout +android.support.design.internal.ForegroundLinearLayout,com.google.android.material.internal.ForegroundLinearLayout +android.support.design.internal.NavigationMenu,com.google.android.material.internal.NavigationMenu +android.support.design.internal.NavigationMenuItemView,com.google.android.material.internal.NavigationMenuItemView +android.support.design.internal.NavigationMenuPresenter,com.google.android.material.internal.NavigationMenuPresenter +android.support.design.internal.NavigationMenuView,com.google.android.material.internal.NavigationMenuView +android.support.design.internal.NavigationSubMenu,com.google.android.material.internal.NavigationSubMenu +android.support.design.internal.ParcelableSparseArray,com.google.android.material.internal.ParcelableSparseArray +android.support.design.internal.ScrimInsetsFrameLayout,com.google.android.material.internal.ScrimInsetsFrameLayout +android.support.design.internal.TextScale,com.google.android.material.internal.TextScale +android.support.design.internal.ThemeEnforcement,com.google.android.material.internal.ThemeEnforcement +android.support.design.internal.ViewUtils,com.google.android.material.internal.ViewUtils +android.support.design.R,com.google.android.material.R +android.support.design.resources.MaterialResources,com.google.android.material.resources.MaterialResources +android.support.design.resources.TextAppearance,com.google.android.material.resources.TextAppearance +android.support.design.resources.TextAppearanceConfig,com.google.android.material.resources.TextAppearanceConfig +android.support.design.ripple.RippleUtils,com.google.android.material.ripple.RippleUtils +android.support.design.shape.CornerTreatment,com.google.android.material.shape.CornerTreatment +android.support.design.shape.CutCornerTreatment,com.google.android.material.shape.CutCornerTreatment +android.support.design.shape.EdgeTreatment,com.google.android.material.shape.EdgeTreatment +android.support.design.shape.InterpolateOnScrollPositionChangeHelper,com.google.android.material.shape.InterpolateOnScrollPositionChangeHelper +android.support.design.shape.MaterialShapeDrawable,com.google.android.material.shape.MaterialShapeDrawable +android.support.design.shape.RoundedCornerTreatment,com.google.android.material.shape.RoundedCornerTreatment +android.support.design.shape.ShapePath,com.google.android.material.shape.ShapePath +android.support.design.shape.ShapePathModel,com.google.android.material.shape.ShapePathModel +android.support.design.shape.TriangleEdgeTreatment,com.google.android.material.shape.TriangleEdgeTreatment +android.support.design.snackbar.ContentViewCallback,com.google.android.material.snackbar.ContentViewCallback +android.support.design.stateful.ExtendableSavedState,com.google.android.material.stateful.ExtendableSavedState +android.support.design.theme.MaterialComponentsViewInflater,com.google.android.material.theme.MaterialComponentsViewInflater +android.support.design.transformation.ExpandableBehavior,com.google.android.material.transformation.ExpandableBehavior +android.support.design.transformation.ExpandableTransformationBehavior,com.google.android.material.transformation.ExpandableTransformationBehavior +android.support.design.transformation.FabTransformationBehavior,com.google.android.material.transformation.FabTransformationBehavior +android.support.design.transformation.FabTransformationScrimBehavior,com.google.android.material.transformation.FabTransformationScrimBehavior +android.support.design.transformation.FabTransformationSheetBehavior,com.google.android.material.transformation.FabTransformationSheetBehavior +android.support.design.transformation.TransformationChildCard,com.google.android.material.transformation.TransformationChildCard +android.support.design.transformation.TransformationChildLayout,com.google.android.material.transformation.TransformationChildLayout +android.support.design.widget.AppBarLayout,com.google.android.material.appbar.AppBarLayout +android.support.design.widget.BaseTransientBottomBar,com.google.android.material.snackbar.BaseTransientBottomBar +android.support.design.widget.BottomNavigationView,com.google.android.material.bottomnavigation.BottomNavigationView +android.support.design.widget.BottomSheetBehavior,com.google.android.material.bottomsheet.BottomSheetBehavior +android.support.design.widget.BottomSheetDialog,com.google.android.material.bottomsheet.BottomSheetDialog +android.support.design.widget.BottomSheetDialogFragment,com.google.android.material.bottomsheet.BottomSheetDialogFragment +android.support.design.widget.CheckableImageButton,com.google.android.material.internal.CheckableImageButton +android.support.design.widget.CircularBorderDrawable,com.google.android.material.internal.CircularBorderDrawable +android.support.design.widget.CircularBorderDrawableLollipop,com.google.android.material.internal.CircularBorderDrawableLollipop +android.support.design.widget.CollapsingTextHelper,com.google.android.material.internal.CollapsingTextHelper +android.support.design.widget.CollapsingToolbarLayout,com.google.android.material.appbar.CollapsingToolbarLayout +android.support.design.widget.CoordinatorLayout,androidx.coordinatorlayout.widget.CoordinatorLayout +android.support.design.widget.CutoutDrawable,com.google.android.material.textfield.CutoutDrawable +android.support.design.widget.DescendantOffsetUtils,com.google.android.material.internal.DescendantOffsetUtils +android.support.design.widget.DrawableUtils,com.google.android.material.internal.DrawableUtils +android.support.design.widget.FloatingActionButton,com.google.android.material.floatingactionbutton.FloatingActionButton +android.support.design.widget.FloatingActionButtonImpl,com.google.android.material.floatingactionbutton.FloatingActionButtonImpl +android.support.design.widget.FloatingActionButtonImplLollipop,com.google.android.material.floatingactionbutton.FloatingActionButtonImplLollipop +android.support.design.widget.HeaderBehavior,com.google.android.material.appbar.HeaderBehavior +android.support.design.widget.HeaderScrollingViewBehavior,com.google.android.material.appbar.HeaderScrollingViewBehavior +android.support.design.widget.IndicatorViewController,com.google.android.material.textfield.IndicatorViewController +android.support.design.widget.MathUtils,com.google.android.material.math.MathUtils +android.support.design.widget.NavigationView,com.google.android.material.navigation.NavigationView +android.support.design.widget.ShadowDrawableWrapper,com.google.android.material.shadow.ShadowDrawableWrapper +android.support.design.widget.ShadowViewDelegate,com.google.android.material.shadow.ShadowViewDelegate +android.support.design.widget.Snackbar,com.google.android.material.snackbar.Snackbar +android.support.design.widget.SnackbarContentLayout,com.google.android.material.snackbar.SnackbarContentLayout +android.support.design.widget.SnackbarManager,com.google.android.material.snackbar.SnackbarManager +android.support.design.widget.StateListAnimator,com.google.android.material.internal.StateListAnimator +android.support.design.widget.SwipeDismissBehavior,com.google.android.material.behavior.SwipeDismissBehavior +android.support.design.widget.TabItem,com.google.android.material.tabs.TabItem +android.support.design.widget.TabLayout,com.google.android.material.tabs.TabLayout +android.support.design.widget.TextInputEditText,com.google.android.material.textfield.TextInputEditText +android.support.design.widget.TextInputLayout,com.google.android.material.textfield.TextInputLayout +android.support.design.widget.ViewOffsetBehavior,com.google.android.material.appbar.ViewOffsetBehavior +android.support.design.widget.ViewOffsetHelper,com.google.android.material.appbar.ViewOffsetHelper +android.support.design.widget.ViewUtilsLollipop,com.google.android.material.appbar.ViewUtilsLollipop +android.support.design.widget.VisibilityAwareImageButton,com.google.android.material.internal.VisibilityAwareImageButton +android.support.graphics.drawable.AndroidResources,androidx.vectordrawable.graphics.drawable.AndroidResources +android.support.graphics.drawable.Animatable2Compat,androidx.vectordrawable.graphics.drawable.Animatable2Compat +android.support.graphics.drawable.AnimatedVectorDrawableCompat,androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat +android.support.graphics.drawable.AnimationUtilsCompat,androidx.vectordrawable.graphics.drawable.AnimationUtilsCompat +android.support.graphics.drawable.AnimatorInflaterCompat,androidx.vectordrawable.graphics.drawable.AnimatorInflaterCompat +android.support.graphics.drawable.ArgbEvaluator,androidx.vectordrawable.graphics.drawable.ArgbEvaluator +android.support.graphics.drawable.PathInterpolatorCompat,androidx.vectordrawable.graphics.drawable.PathInterpolatorCompat +android.support.graphics.drawable.VectorDrawableCommon,androidx.vectordrawable.graphics.drawable.VectorDrawableCommon +android.support.graphics.drawable.VectorDrawableCompat,androidx.vectordrawable.graphics.drawable.VectorDrawableCompat +android.support.media.ExifInterface,androidx.exifinterface.media.ExifInterface +android.support.media.tv.BasePreviewProgram,androidx.tvprovider.media.tv.BasePreviewProgram +android.support.media.tv.BaseProgram,androidx.tvprovider.media.tv.BaseProgram +android.support.media.tv.Channel,androidx.tvprovider.media.tv.Channel +android.support.media.tv.ChannelLogoUtils,androidx.tvprovider.media.tv.ChannelLogoUtils +android.support.media.tv.CollectionUtils,androidx.tvprovider.media.tv.CollectionUtils +android.support.media.tv.PreviewChannel,androidx.tvprovider.media.tv.PreviewChannel +android.support.media.tv.PreviewChannelHelper,androidx.tvprovider.media.tv.PreviewChannelHelper +android.support.media.tv.PreviewProgram,androidx.tvprovider.media.tv.PreviewProgram +android.support.media.tv.Program,androidx.tvprovider.media.tv.Program +android.support.media.tv.TvContractCompat,androidx.tvprovider.media.tv.TvContractCompat +android.support.media.tv.TvContractUtils,androidx.tvprovider.media.tv.TvContractUtils +android.support.media.tv.WatchNextProgram,androidx.tvprovider.media.tv.WatchNextProgram +android.support.media2.BaseRemoteMediaPlayerConnector,android.support.media2.BaseRemoteMediaPlayerConnector +android.support.media2.DataSourceDesc2,android.support.media2.DataSourceDesc2 +android.support.media2.MediaPlayerConnector,android.support.media2.MediaPlayerConnector +android.support.media2.MediaPlaylistAgent,android.support.media2.MediaPlaylistAgent +android.support.media2.MediaSession2,android.support.media2.MediaSession2 +android.support.mediacompat.R,androidx.media.R +android.support.multidex.MultiDex,androidx.multidex.MultiDex +android.support.multidex.MultiDexApplication,androidx.multidex.MultiDexApplication +android.support.multidex.MultiDexExtractor,androidx.multidex.MultiDexExtractor +android.support.multidex.ZipUtil,androidx.multidex.ZipUtil +android.support.percent.PercentFrameLayout,androidx.percentlayout.widget.PercentFrameLayout +android.support.percent.PercentLayoutHelper,androidx.percentlayout.widget.PercentLayoutHelper +android.support.percent.PercentRelativeLayout,androidx.percentlayout.widget.PercentRelativeLayout +android.support.percent.R,androidx.percentlayout.R +android.support.test.annotation.Beta,androidx.test.annotation.Beta +android.support.test.annotation.UiThreadTest,androidx.test.annotation.UiThreadTest +android.support.test.espresso.accessibility.AccessibilityChecks,androidx.test.espresso.accessibility.AccessibilityChecks +android.support.test.espresso.action.AdapterDataLoaderAction,androidx.test.espresso.action.AdapterDataLoaderAction +android.support.test.espresso.action.AdapterDataLoaderActionRemoteMsg,androidx.test.espresso.action.AdapterDataLoaderActionRemoteMsg +android.support.test.espresso.action.AdapterViewProtocol,androidx.test.espresso.action.AdapterViewProtocol +android.support.test.espresso.action.AdapterViewProtocols,androidx.test.espresso.action.AdapterViewProtocols +android.support.test.espresso.action.CloseKeyboardAction,androidx.test.espresso.action.CloseKeyboardAction +android.support.test.espresso.action.CoordinatesProvider,androidx.test.espresso.action.CoordinatesProvider +android.support.test.espresso.action.EditorAction,androidx.test.espresso.action.EditorAction +android.support.test.espresso.action.EspressoKey,androidx.test.espresso.action.EspressoKey +android.support.test.espresso.action.GeneralClickAction,androidx.test.espresso.action.GeneralClickAction +android.support.test.espresso.action.GeneralClickActionRemoteMessage,androidx.test.espresso.action.GeneralClickActionRemoteMessage +android.support.test.espresso.action.GeneralLocation,androidx.test.espresso.action.GeneralLocation +android.support.test.espresso.action.GeneralLocationRemoteMessage,androidx.test.espresso.action.GeneralLocationRemoteMessage +android.support.test.espresso.action.GeneralSwipeAction,androidx.test.espresso.action.GeneralSwipeAction +android.support.test.espresso.action.GeneralSwipeActionRemoteMessage,androidx.test.espresso.action.GeneralSwipeActionRemoteMessage +android.support.test.espresso.action.KeyEventAction,androidx.test.espresso.action.KeyEventAction +android.support.test.espresso.action.KeyEventActionBase,androidx.test.espresso.action.KeyEventActionBase +android.support.test.espresso.action.MotionEvents,androidx.test.espresso.action.MotionEvents +android.support.test.espresso.action.OpenLinkAction,androidx.test.espresso.action.OpenLinkAction +android.support.test.espresso.action.PrecisionDescriber,androidx.test.espresso.action.PrecisionDescriber +android.support.test.espresso.action.Press,androidx.test.espresso.action.Press +android.support.test.espresso.action.PressBackAction,androidx.test.espresso.action.PressBackAction +android.support.test.espresso.action.PressRemoteMessage,androidx.test.espresso.action.PressRemoteMessage +android.support.test.espresso.action.RemoteViewActions,androidx.test.espresso.action.RemoteViewActions +android.support.test.espresso.action.RepeatActionUntilViewState,androidx.test.espresso.action.RepeatActionUntilViewState +android.support.test.espresso.action.ReplaceTextAction,androidx.test.espresso.action.ReplaceTextAction +android.support.test.espresso.action.ScrollToAction,androidx.test.espresso.action.ScrollToAction +android.support.test.espresso.action.Swipe,androidx.test.espresso.action.Swipe +android.support.test.espresso.action.Swiper,androidx.test.espresso.action.Swiper +android.support.test.espresso.action.SwipeRemoteMessage,androidx.test.espresso.action.SwipeRemoteMessage +android.support.test.espresso.action.Tap,androidx.test.espresso.action.Tap +android.support.test.espresso.action.Tapper,androidx.test.espresso.action.Tapper +android.support.test.espresso.action.TapRemoteMessage,androidx.test.espresso.action.TapRemoteMessage +android.support.test.espresso.action.TranslatedCoordinatesProvider,androidx.test.espresso.action.TranslatedCoordinatesProvider +android.support.test.espresso.action.TranslatedCoordinatesProviderRemoteMessage,androidx.test.espresso.action.TranslatedCoordinatesProviderRemoteMessage +android.support.test.espresso.action.TypeTextAction,androidx.test.espresso.action.TypeTextAction +android.support.test.espresso.action.ViewActions,androidx.test.espresso.action.ViewActions +android.support.test.espresso.AmbiguousViewMatcherException,androidx.test.espresso.AmbiguousViewMatcherException +android.support.test.espresso.AppNotIdleException,androidx.test.espresso.AppNotIdleException +android.support.test.espresso.assertion.LayoutAssertions,androidx.test.espresso.assertion.LayoutAssertions +android.support.test.espresso.assertion.PositionAssertions,androidx.test.espresso.assertion.PositionAssertions +android.support.test.espresso.assertion.RemoteViewAssertions,androidx.test.espresso.assertion.RemoteViewAssertions +android.support.test.espresso.assertion.ViewAssertions,androidx.test.espresso.assertion.ViewAssertions +android.support.test.espresso.base.ActiveRootLister,androidx.test.espresso.base.ActiveRootLister +android.support.test.espresso.base.AsyncTaskPoolMonitor,androidx.test.espresso.base.AsyncTaskPoolMonitor +android.support.test.espresso.base.BaseLayerModule,androidx.test.espresso.base.BaseLayerModule +android.support.test.espresso.base.BaseLayerModule_FailureHandlerHolder_Factory,androidx.test.espresso.base.BaseLayerModule_FailureHandlerHolder_Factory +android.support.test.espresso.base.BaseLayerModule_ProvideActiveRootListerFactory,androidx.test.espresso.base.BaseLayerModule_ProvideActiveRootListerFactory +android.support.test.espresso.base.BaseLayerModule_ProvideCompatAsyncTaskMonitorFactory,androidx.test.espresso.base.BaseLayerModule_ProvideCompatAsyncTaskMonitorFactory +android.support.test.espresso.base.BaseLayerModule_ProvideDynamicNotiferFactory,androidx.test.espresso.base.BaseLayerModule_ProvideDynamicNotiferFactory +android.support.test.espresso.base.BaseLayerModule_ProvideEventInjectorFactory,androidx.test.espresso.base.BaseLayerModule_ProvideEventInjectorFactory +android.support.test.espresso.base.BaseLayerModule_ProvideFailureHanderFactory,androidx.test.espresso.base.BaseLayerModule_ProvideFailureHanderFactory +android.support.test.espresso.base.BaseLayerModule_ProvideFailureHandlerFactory,androidx.test.espresso.base.BaseLayerModule_ProvideFailureHandlerFactory +android.support.test.espresso.base.BaseLayerModule_ProvideLifecycleMonitorFactory,androidx.test.espresso.base.BaseLayerModule_ProvideLifecycleMonitorFactory +android.support.test.espresso.base.BaseLayerModule_ProvideMainLooperFactory,androidx.test.espresso.base.BaseLayerModule_ProvideMainLooperFactory +android.support.test.espresso.base.BaseLayerModule_ProvideMainThreadExecutorFactory,androidx.test.espresso.base.BaseLayerModule_ProvideMainThreadExecutorFactory +android.support.test.espresso.base.BaseLayerModule_ProvideRemoteExecutorFactory,androidx.test.espresso.base.BaseLayerModule_ProvideRemoteExecutorFactory +android.support.test.espresso.base.BaseLayerModule_ProvideSdkAsyncTaskMonitorFactory,androidx.test.espresso.base.BaseLayerModule_ProvideSdkAsyncTaskMonitorFactory +android.support.test.espresso.base.BaseLayerModule_ProvideTargetContextFactory,androidx.test.espresso.base.BaseLayerModule_ProvideTargetContextFactory +android.support.test.espresso.base.CompatAsyncTask,androidx.test.espresso.base.CompatAsyncTask +android.support.test.espresso.base.Default,androidx.test.espresso.base.Default +android.support.test.espresso.base.DefaultFailureHandler,androidx.test.espresso.base.DefaultFailureHandler +android.support.test.espresso.base.EventInjectionStrategy,androidx.test.espresso.base.EventInjectionStrategy +android.support.test.espresso.base.EventInjector,androidx.test.espresso.base.EventInjector +android.support.test.espresso.base.IdleNotifier,androidx.test.espresso.base.IdleNotifier +android.support.test.espresso.base.IdlingResourceRegistry,androidx.test.espresso.base.IdlingResourceRegistry +android.support.test.espresso.base.IdlingResourceRegistry_Factory,androidx.test.espresso.base.IdlingResourceRegistry_Factory +android.support.test.espresso.base.IdlingUiController,androidx.test.espresso.base.IdlingUiController +android.support.test.espresso.base.InputManagerEventInjectionStrategy,androidx.test.espresso.base.InputManagerEventInjectionStrategy +android.support.test.espresso.base.Interrogator,androidx.test.espresso.base.Interrogator +android.support.test.espresso.base.InterruptableUiController,androidx.test.espresso.base.InterruptableUiController +android.support.test.espresso.base.LooperIdlingResourceInterrogationHandler,androidx.test.espresso.base.LooperIdlingResourceInterrogationHandler +android.support.test.espresso.base.MainThread,androidx.test.espresso.base.MainThread +android.support.test.espresso.base.NoopIdleNotificationCallbackIdleNotifierProvider,androidx.test.espresso.base.NoopIdleNotificationCallbackIdleNotifierProvider +android.support.test.espresso.base.NoopRunnableIdleNotifier,androidx.test.espresso.base.NoopRunnableIdleNotifier +android.support.test.espresso.base.RootsOracle,androidx.test.espresso.base.RootsOracle +android.support.test.espresso.base.RootsOracle_Factory,androidx.test.espresso.base.RootsOracle_Factory +android.support.test.espresso.base.RootViewPicker,androidx.test.espresso.base.RootViewPicker +android.support.test.espresso.base.RootViewPicker_Factory,androidx.test.espresso.base.RootViewPicker_Factory +android.support.test.espresso.base.RootViewPicker_RootResultFetcher_Factory,androidx.test.espresso.base.RootViewPicker_RootResultFetcher_Factory +android.support.test.espresso.base.RootViewPickerScope,androidx.test.espresso.base.RootViewPickerScope +android.support.test.espresso.base.SdkAsyncTask,androidx.test.espresso.base.SdkAsyncTask +android.support.test.espresso.base.ThreadPoolExecutorExtractor,androidx.test.espresso.base.ThreadPoolExecutorExtractor +android.support.test.espresso.base.ThreadPoolExecutorExtractor_Factory,androidx.test.espresso.base.ThreadPoolExecutorExtractor_Factory +android.support.test.espresso.base.UiControllerImpl,androidx.test.espresso.base.UiControllerImpl +android.support.test.espresso.base.UiControllerImpl_Factory,androidx.test.espresso.base.UiControllerImpl_Factory +android.support.test.espresso.base.UiControllerModule,androidx.test.espresso.base.UiControllerModule +android.support.test.espresso.base.ViewFinderImpl,androidx.test.espresso.base.ViewFinderImpl +android.support.test.espresso.base.ViewFinderImpl_Factory,androidx.test.espresso.base.ViewFinderImpl_Factory +android.support.test.espresso.base.WindowManagerEventInjectionStrategy,androidx.test.espresso.base.WindowManagerEventInjectionStrategy +android.support.test.espresso.BaseLayerComponent,androidx.test.espresso.BaseLayerComponent +android.support.test.espresso.contrib.AccessibilityChecks,androidx.test.espresso.contrib.AccessibilityChecks +android.support.test.espresso.contrib.ActivityResultMatchers,androidx.test.espresso.contrib.ActivityResultMatchers +android.support.test.espresso.contrib.Checks,androidx.test.espresso.contrib.Checks +android.support.test.espresso.contrib.DrawerActions,androidx.test.espresso.contrib.DrawerActions +android.support.test.espresso.contrib.DrawerMatchers,androidx.test.espresso.contrib.DrawerMatchers +android.support.test.espresso.contrib.NavigationViewActions,androidx.test.espresso.contrib.NavigationViewActions +android.support.test.espresso.contrib.PickerActions,androidx.test.espresso.contrib.PickerActions +android.support.test.espresso.contrib.RecyclerViewActions,androidx.test.espresso.contrib.RecyclerViewActions +android.support.test.espresso.contrib.ViewPagerActions,androidx.test.espresso.contrib.ViewPagerActions +android.support.test.espresso.DaggerBaseLayerComponent,androidx.test.espresso.DaggerBaseLayerComponent +android.support.test.espresso.DataInteraction,androidx.test.espresso.DataInteraction +android.support.test.espresso.DataInteractionRemote,androidx.test.espresso.DataInteractionRemote +android.support.test.espresso.Espresso,androidx.test.espresso.Espresso +android.support.test.espresso.EspressoException,androidx.test.espresso.EspressoException +android.support.test.espresso.FailureHandler,androidx.test.espresso.FailureHandler +android.support.test.espresso.GraphHolder,androidx.test.espresso.GraphHolder +android.support.test.espresso.idling.concurrent.IdlingScheduledThreadPoolExecutor,androidx.test.espresso.idling.concurrent.IdlingScheduledThreadPoolExecutor +android.support.test.espresso.idling.concurrent.IdlingThreadPoolExecutor,androidx.test.espresso.idling.concurrent.IdlingThreadPoolExecutor +android.support.test.espresso.idling.CountingIdlingResource,androidx.test.espresso.idling.CountingIdlingResource +android.support.test.espresso.idling.net.UriIdlingResource,androidx.test.espresso.idling.net.UriIdlingResource +android.support.test.espresso.IdlingPolicies,androidx.test.espresso.IdlingPolicies +android.support.test.espresso.IdlingPolicy,androidx.test.espresso.IdlingPolicy +android.support.test.espresso.IdlingRegistry,androidx.test.espresso.IdlingRegistry +android.support.test.espresso.IdlingResource,androidx.test.espresso.IdlingResource +android.support.test.espresso.IdlingResourceTimeoutException,androidx.test.espresso.IdlingResourceTimeoutException +android.support.test.espresso.InjectEventSecurityException,androidx.test.espresso.InjectEventSecurityException +android.support.test.espresso.intent.ActivityResultFunction,androidx.test.espresso.intent.ActivityResultFunction +android.support.test.espresso.intent.Checks,androidx.test.espresso.intent.Checks +android.support.test.espresso.intent.Intents,androidx.test.espresso.intent.Intents +android.support.test.espresso.intent.matcher.BundleMatchers,androidx.test.espresso.intent.matcher.BundleMatchers +android.support.test.espresso.intent.matcher.ComponentNameMatchers,androidx.test.espresso.intent.matcher.ComponentNameMatchers +android.support.test.espresso.intent.matcher.IntentMatchers,androidx.test.espresso.intent.matcher.IntentMatchers +android.support.test.espresso.intent.matcher.UriMatchers,androidx.test.espresso.intent.matcher.UriMatchers +android.support.test.espresso.intent.OngoingStubbing,androidx.test.espresso.intent.OngoingStubbing +android.support.test.espresso.intent.ResettingStubber,androidx.test.espresso.intent.ResettingStubber +android.support.test.espresso.intent.ResettingStubberImpl,androidx.test.espresso.intent.ResettingStubberImpl +android.support.test.espresso.intent.ResolvedIntent,androidx.test.espresso.intent.ResolvedIntent +android.support.test.espresso.intent.ResolvedIntentImpl,androidx.test.espresso.intent.ResolvedIntentImpl +android.support.test.espresso.intent.rule.IntentsTestRule,androidx.test.espresso.intent.rule.IntentsTestRule +android.support.test.espresso.intent.VerifiableIntent,androidx.test.espresso.intent.VerifiableIntent +android.support.test.espresso.intent.VerifiableIntentImpl,androidx.test.espresso.intent.VerifiableIntentImpl +android.support.test.espresso.intent.VerificationMode,androidx.test.espresso.intent.VerificationMode +android.support.test.espresso.intent.VerificationModes,androidx.test.espresso.intent.VerificationModes +android.support.test.espresso.InteractionResultsHandler,androidx.test.espresso.InteractionResultsHandler +android.support.test.espresso.matcher.BoundedMatcher,androidx.test.espresso.matcher.BoundedMatcher +android.support.test.espresso.matcher.CursorMatchers,androidx.test.espresso.matcher.CursorMatchers +android.support.test.espresso.matcher.HasBackgroundMatcher,androidx.test.espresso.matcher.HasBackgroundMatcher +android.support.test.espresso.matcher.LayoutMatchers,androidx.test.espresso.matcher.LayoutMatchers +android.support.test.espresso.matcher.PreferenceMatchers,androidx.test.espresso.matcher.PreferenceMatchers +android.support.test.espresso.matcher.RemoteHamcrestCoreMatchers13,androidx.test.espresso.matcher.RemoteHamcrestCoreMatchers13 +android.support.test.espresso.matcher.RemoteRootMatchers,androidx.test.espresso.matcher.RemoteRootMatchers +android.support.test.espresso.matcher.RemoteViewMatchers,androidx.test.espresso.matcher.RemoteViewMatchers +android.support.test.espresso.matcher.RootMatchers,androidx.test.espresso.matcher.RootMatchers +android.support.test.espresso.matcher.ViewMatchers,androidx.test.espresso.matcher.ViewMatchers +android.support.test.espresso.NoActivityResumedException,androidx.test.espresso.NoActivityResumedException +android.support.test.espresso.NoMatchingRootException,androidx.test.espresso.NoMatchingRootException +android.support.test.espresso.NoMatchingViewException,androidx.test.espresso.NoMatchingViewException +android.support.test.espresso.PerformException,androidx.test.espresso.PerformException +android.support.test.espresso.proto.action.ViewActions,androidx.test.espresso.proto.action.ViewActions +android.support.test.espresso.proto.assertion.ViewAssertions,androidx.test.espresso.proto.assertion.ViewAssertions +android.support.test.espresso.proto.matcher.RootMatchers,androidx.test.espresso.proto.matcher.RootMatchers +android.support.test.espresso.proto.matcher.ViewMatchers,androidx.test.espresso.proto.matcher.ViewMatchers +android.support.test.espresso.proto.matcher13.HamcrestMatchersv13,androidx.test.espresso.proto.matcher13.HamcrestMatchersv13 +android.support.test.espresso.proto.UiInteraction,androidx.test.espresso.proto.UiInteraction +android.support.test.espresso.remote.annotation.RemoteMsgConstructor,androidx.test.espresso.remote.annotation.RemoteMsgConstructor +android.support.test.espresso.remote.annotation.RemoteMsgField,androidx.test.espresso.remote.annotation.RemoteMsgField +android.support.test.espresso.remote.AnyToTypeConverter,androidx.test.espresso.remote.AnyToTypeConverter +android.support.test.espresso.remote.Bindable,androidx.test.espresso.remote.Bindable +android.support.test.espresso.remote.BuilderReflector,androidx.test.espresso.remote.BuilderReflector +android.support.test.espresso.remote.ByteStringToParcelableConverter,androidx.test.espresso.remote.ByteStringToParcelableConverter +android.support.test.espresso.remote.ByteStringToTypeConverter,androidx.test.espresso.remote.ByteStringToTypeConverter +android.support.test.espresso.remote.ConstructorInvocation,androidx.test.espresso.remote.ConstructorInvocation +android.support.test.espresso.remote.Converter,androidx.test.espresso.remote.Converter +android.support.test.espresso.remote.EspressoRemote,androidx.test.espresso.remote.EspressoRemote +android.support.test.espresso.remote.EspressoRemoteMessage,androidx.test.espresso.remote.EspressoRemoteMessage +android.support.test.espresso.remote.FieldDescriptor,androidx.test.espresso.remote.FieldDescriptor +android.support.test.espresso.remote.GenericRemoteMessage,androidx.test.espresso.remote.GenericRemoteMessage +android.support.test.espresso.remote.IInteractionExecutionStatus,androidx.test.espresso.remote.IInteractionExecutionStatus +android.support.test.espresso.remote.InteractionRequest,androidx.test.espresso.remote.InteractionRequest +android.support.test.espresso.remote.InteractionResponse,androidx.test.espresso.remote.InteractionResponse +android.support.test.espresso.remote.MethodInvocation,androidx.test.espresso.remote.MethodInvocation +android.support.test.espresso.remote.NoopRemoteInteraction,androidx.test.espresso.remote.NoopRemoteInteraction +android.support.test.espresso.remote.NoRemoteEspressoInstanceException,androidx.test.espresso.remote.NoRemoteEspressoInstanceException +android.support.test.espresso.remote.ParcelableToByteStringConverter,androidx.test.espresso.remote.ParcelableToByteStringConverter +android.support.test.espresso.remote.ProtoReflector,androidx.test.espresso.remote.ProtoReflector +android.support.test.espresso.remote.ProtoUtils,androidx.test.espresso.remote.ProtoUtils +android.support.test.espresso.remote.RemoteDescriptor,androidx.test.espresso.remote.RemoteDescriptor +android.support.test.espresso.remote.RemoteDescriptorRegistry,androidx.test.espresso.remote.RemoteDescriptorRegistry +android.support.test.espresso.remote.RemoteEspressoException,androidx.test.espresso.remote.RemoteEspressoException +android.support.test.espresso.remote.RemoteInteraction,androidx.test.espresso.remote.RemoteInteraction +android.support.test.espresso.remote.RemoteInteractionRegistry,androidx.test.espresso.remote.RemoteInteractionRegistry +android.support.test.espresso.remote.RemoteMessageDeserializer,androidx.test.espresso.remote.RemoteMessageDeserializer +android.support.test.espresso.remote.RemoteMessageSerializer,androidx.test.espresso.remote.RemoteMessageSerializer +android.support.test.espresso.remote.RemoteProtocolException,androidx.test.espresso.remote.RemoteProtocolException +android.support.test.espresso.remote.TypeProtoConverters,androidx.test.espresso.remote.TypeProtoConverters +android.support.test.espresso.remote.TypeToAnyConverter,androidx.test.espresso.remote.TypeToAnyConverter +android.support.test.espresso.remote.TypeToByteStringConverter,androidx.test.espresso.remote.TypeToByteStringConverter +android.support.test.espresso.Root,androidx.test.espresso.Root +android.support.test.espresso.UiController,androidx.test.espresso.UiController +android.support.test.espresso.util.ActivityLifecycles,androidx.test.espresso.util.ActivityLifecycles +android.support.test.espresso.util.EspressoOptional,androidx.test.espresso.util.EspressoOptional +android.support.test.espresso.util.HumanReadables,androidx.test.espresso.util.HumanReadables +android.support.test.espresso.util.TreeIterables,androidx.test.espresso.util.TreeIterables +android.support.test.espresso.ViewAction,androidx.test.espresso.ViewAction +android.support.test.espresso.ViewAssertion,androidx.test.espresso.ViewAssertion +android.support.test.espresso.ViewFinder,androidx.test.espresso.ViewFinder +android.support.test.espresso.ViewInteraction,androidx.test.espresso.ViewInteraction +android.support.test.espresso.ViewInteraction_Factory,androidx.test.espresso.ViewInteraction_Factory +android.support.test.espresso.ViewInteractionComponent,androidx.test.espresso.ViewInteractionComponent +android.support.test.espresso.ViewInteractionModule,androidx.test.espresso.ViewInteractionModule +android.support.test.espresso.ViewInteractionModule_ProvideNeedsActivityFactory,androidx.test.espresso.ViewInteractionModule_ProvideNeedsActivityFactory +android.support.test.espresso.ViewInteractionModule_ProvideRemoteInteractionFactory,androidx.test.espresso.ViewInteractionModule_ProvideRemoteInteractionFactory +android.support.test.espresso.ViewInteractionModule_ProvideRootMatcherFactory,androidx.test.espresso.ViewInteractionModule_ProvideRootMatcherFactory +android.support.test.espresso.ViewInteractionModule_ProvideRootViewFactory,androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory +android.support.test.espresso.ViewInteractionModule_ProvideViewFinderFactory,androidx.test.espresso.ViewInteractionModule_ProvideViewFinderFactory +android.support.test.espresso.ViewInteractionModule_ProvideViewMatcherFactory,androidx.test.espresso.ViewInteractionModule_ProvideViewMatcherFactory +android.support.test.espresso.web.action.AtomAction,androidx.test.espresso.web.action.AtomAction +android.support.test.espresso.web.action.AtomActionRemoteMessage,androidx.test.espresso.web.action.AtomActionRemoteMessage +android.support.test.espresso.web.action.EnableJavascriptAction,androidx.test.espresso.web.action.EnableJavascriptAction +android.support.test.espresso.web.action.EvaluationAtom,androidx.test.espresso.web.action.EvaluationAtom +android.support.test.espresso.web.action.IAtomActionResultPropagator,androidx.test.espresso.web.action.IAtomActionResultPropagator +android.support.test.espresso.web.action.JavascriptEvaluation,androidx.test.espresso.web.action.JavascriptEvaluation +android.support.test.espresso.web.action.RemoteWebActions,androidx.test.espresso.web.action.RemoteWebActions +android.support.test.espresso.web.assertion.ByteStringToDocumentConverter,androidx.test.espresso.web.assertion.ByteStringToDocumentConverter +android.support.test.espresso.web.assertion.CheckResultWebAssertionRemoteMessage,androidx.test.espresso.web.assertion.CheckResultWebAssertionRemoteMessage +android.support.test.espresso.web.assertion.CompressorDecompressor,androidx.test.espresso.web.assertion.CompressorDecompressor +android.support.test.espresso.web.assertion.DocumentProtoConverters,androidx.test.espresso.web.assertion.DocumentProtoConverters +android.support.test.espresso.web.assertion.DocumentToByteStringConverter,androidx.test.espresso.web.assertion.DocumentToByteStringConverter +android.support.test.espresso.web.assertion.RemoteWebViewAssertions,androidx.test.espresso.web.assertion.RemoteWebViewAssertions +android.support.test.espresso.web.assertion.TagSoupDocumentParser,androidx.test.espresso.web.assertion.TagSoupDocumentParser +android.support.test.espresso.web.assertion.WebAssertion,androidx.test.espresso.web.assertion.WebAssertion +android.support.test.espresso.web.assertion.WebViewAssertions,androidx.test.espresso.web.assertion.WebViewAssertions +android.support.test.espresso.web.matcher.AmbiguousElementMatcherException,androidx.test.espresso.web.matcher.AmbiguousElementMatcherException +android.support.test.espresso.web.matcher.DomMatchers,androidx.test.espresso.web.matcher.DomMatchers +android.support.test.espresso.web.matcher.RemoteWebMatchers,androidx.test.espresso.web.matcher.RemoteWebMatchers +android.support.test.espresso.web.model.Atom,androidx.test.espresso.web.model.Atom +android.support.test.espresso.web.model.Atoms,androidx.test.espresso.web.model.Atoms +android.support.test.espresso.web.model.ElementReference,androidx.test.espresso.web.model.ElementReference +android.support.test.espresso.web.model.Evaluation,androidx.test.espresso.web.model.Evaluation +android.support.test.espresso.web.model.JSONAble,androidx.test.espresso.web.model.JSONAble +android.support.test.espresso.web.model.ModelCodec,androidx.test.espresso.web.model.ModelCodec +android.support.test.espresso.web.model.RemoteWebModelAtoms,androidx.test.espresso.web.model.RemoteWebModelAtoms +android.support.test.espresso.web.model.ScriptWithArgsSimpleAtomRemoteMessage,androidx.test.espresso.web.model.ScriptWithArgsSimpleAtomRemoteMessage +android.support.test.espresso.web.model.SimpleAtom,androidx.test.espresso.web.model.SimpleAtom +android.support.test.espresso.web.model.TransformingAtom,androidx.test.espresso.web.model.TransformingAtom +android.support.test.espresso.web.model.WindowReference,androidx.test.espresso.web.model.WindowReference +android.support.test.espresso.web.proto.action.WebActions,androidx.test.espresso.web.proto.action.WebActions +android.support.test.espresso.web.proto.assertion.WebAssertions,androidx.test.espresso.web.proto.assertion.WebAssertions +android.support.test.espresso.web.proto.matcher.RemoteWebMatchers,androidx.test.espresso.web.proto.matcher.RemoteWebMatchers +android.support.test.espresso.web.proto.model.WebModelAtoms,androidx.test.espresso.web.proto.model.WebModelAtoms +android.support.test.espresso.web.proto.sugar.WebSugar,androidx.test.espresso.web.proto.sugar.WebSugar +android.support.test.espresso.web.proto.webdriver.WebWebdriverAtoms,androidx.test.espresso.web.proto.webdriver.WebWebdriverAtoms +android.support.test.espresso.web.sugar.RemoteWebSugar,androidx.test.espresso.web.sugar.RemoteWebSugar +android.support.test.espresso.web.sugar.Web,androidx.test.espresso.web.sugar.Web +android.support.test.espresso.web.webdriver.DriverAtoms,androidx.test.espresso.web.webdriver.DriverAtoms +android.support.test.espresso.web.webdriver.Locator,androidx.test.espresso.web.webdriver.Locator +android.support.test.espresso.web.webdriver.RemoteWebDriverAtoms,androidx.test.espresso.web.webdriver.RemoteWebDriverAtoms +android.support.test.espresso.web.webdriver.WebDriverAtomScripts,androidx.test.espresso.web.webdriver.WebDriverAtomScripts +android.support.test.filters.FlakyTest,androidx.test.filters.FlakyTest +android.support.test.filters.LargeTest,androidx.test.filters.LargeTest +android.support.test.filters.MediumTest,androidx.test.filters.MediumTest +android.support.test.filters.RequiresDevice,androidx.test.filters.RequiresDevice +android.support.test.filters.SdkSuppress,androidx.test.filters.SdkSuppress +android.support.test.filters.SmallTest,androidx.test.filters.SmallTest +android.support.test.filters.Suppress,androidx.test.filters.Suppress +android.support.test.InstrumentationRegistry,androidx.test.InstrumentationRegistry +android.support.test.jank.GfxMonitor,androidx.test.jank.GfxMonitor +android.support.test.jank.JankTest,androidx.test.jank.JankTest +android.support.test.jank.JankTestBase,androidx.test.jank.JankTestBase +android.support.test.jank.WindowAnimationFrameStatsMonitor,androidx.test.jank.WindowAnimationFrameStatsMonitor +android.support.test.jank.WindowContentFrameStatsMonitor,androidx.test.jank.WindowContentFrameStatsMonitor +android.support.test.orchestrator.callback.OrchestratorCallback,androidx.test.orchestrator.callback.OrchestratorCallback +android.support.test.orchestrator.instrumentationlistener.OrchestratedInstrumentationListener,androidx.test.orchestrator.instrumentationlistener.OrchestratedInstrumentationListener +android.support.test.orchestrator.junit.BundleJUnitUtils,androidx.test.orchestrator.junit.BundleJUnitUtils +android.support.test.orchestrator.junit.ParcelableDescription,androidx.test.orchestrator.junit.ParcelableDescription +android.support.test.orchestrator.junit.ParcelableFailure,androidx.test.orchestrator.junit.ParcelableFailure +android.support.test.orchestrator.junit.ParcelableResult,androidx.test.orchestrator.junit.ParcelableResult +android.support.test.orchestrator.listeners.OrchestrationListenerManager,androidx.test.orchestrator.listeners.OrchestrationListenerManager +android.support.test.orchestrator.listeners.OrchestrationRunListener,androidx.test.orchestrator.listeners.OrchestrationRunListener +android.support.test.orchestrator.listeners.result.ITestRunListener,androidx.test.orchestrator.listeners.result.ITestRunListener +android.support.test.orchestrator.listeners.result.TestIdentifier,androidx.test.orchestrator.listeners.result.TestIdentifier +android.support.test.orchestrator.listeners.result.TestResult,androidx.test.orchestrator.listeners.result.TestResult +android.support.test.orchestrator.listeners.result.TestRunResult,androidx.test.orchestrator.listeners.result.TestRunResult +android.support.test.rule.ActivityTestRule,androidx.test.rule.ActivityTestRule +android.support.test.rule.DisableOnAndroidDebug,androidx.test.rule.DisableOnAndroidDebug +android.support.test.rule.GrantPermissionRule,androidx.test.rule.GrantPermissionRule +android.support.test.rule.logging.AtraceLogger,androidx.test.rule.logging.AtraceLogger +android.support.test.rule.PortForwardingRule,androidx.test.rule.PortForwardingRule +android.support.test.rule.provider.DatabaseArgs,androidx.test.rule.provider.DatabaseArgs +android.support.test.rule.provider.DelegatingContext,androidx.test.rule.provider.DelegatingContext +android.support.test.rule.provider.ProviderArgs,androidx.test.rule.provider.ProviderArgs +android.support.test.rule.provider.ProviderTestRule,androidx.test.rule.provider.ProviderTestRule +android.support.test.rule.ServiceTestRule,androidx.test.rule.ServiceTestRule +android.support.test.rule.UiThreadTestRule,androidx.test.rule.UiThreadTestRule +android.support.test.runner.AndroidJUnit4,androidx.test.runner.AndroidJUnit4 +android.support.test.runner.AndroidJUnitRunner,androidx.test.runner.AndroidJUnitRunner +android.support.test.runner.intent.IntentCallback,androidx.test.runner.intent.IntentCallback +android.support.test.runner.intent.IntentMonitor,androidx.test.runner.intent.IntentMonitor +android.support.test.runner.intent.IntentMonitorRegistry,androidx.test.runner.intent.IntentMonitorRegistry +android.support.test.runner.intent.IntentStubber,androidx.test.runner.intent.IntentStubber +android.support.test.runner.intent.IntentStubberRegistry,androidx.test.runner.intent.IntentStubberRegistry +android.support.test.runner.intercepting.InterceptingActivityFactory,androidx.test.runner.intercepting.InterceptingActivityFactory +android.support.test.runner.intercepting.SingleActivityFactory,androidx.test.runner.intercepting.SingleActivityFactory +android.support.test.runner.lifecycle.ActivityLifecycleCallback,androidx.test.runner.lifecycle.ActivityLifecycleCallback +android.support.test.runner.lifecycle.ActivityLifecycleMonitor,androidx.test.runner.lifecycle.ActivityLifecycleMonitor +android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry,androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry +android.support.test.runner.lifecycle.ApplicationLifecycleCallback,androidx.test.runner.lifecycle.ApplicationLifecycleCallback +android.support.test.runner.lifecycle.ApplicationLifecycleMonitor,androidx.test.runner.lifecycle.ApplicationLifecycleMonitor +android.support.test.runner.lifecycle.ApplicationLifecycleMonitorRegistry,androidx.test.runner.lifecycle.ApplicationLifecycleMonitorRegistry +android.support.test.runner.lifecycle.ApplicationStage,androidx.test.runner.lifecycle.ApplicationStage +android.support.test.runner.lifecycle.Stage,androidx.test.runner.lifecycle.Stage +android.support.test.runner.MonitoringInstrumentation,androidx.test.runner.MonitoringInstrumentation +android.support.test.runner.permission.GrantPermissionCallable,androidx.test.runner.permission.GrantPermissionCallable +android.support.test.runner.permission.PermissionRequester,androidx.test.runner.permission.PermissionRequester +android.support.test.runner.permission.RequestPermissionCallable,androidx.test.runner.permission.RequestPermissionCallable +android.support.test.runner.permission.ShellCommand,androidx.test.runner.permission.ShellCommand +android.support.test.runner.permission.UiAutomationShellCommand,androidx.test.runner.permission.UiAutomationShellCommand +android.support.test.runner.screenshot.BasicScreenCaptureProcessor,androidx.test.runner.screenshot.BasicScreenCaptureProcessor +android.support.test.runner.screenshot.ScreenCapture,androidx.test.runner.screenshot.ScreenCapture +android.support.test.runner.screenshot.ScreenCaptureProcessor,androidx.test.runner.screenshot.ScreenCaptureProcessor +android.support.test.runner.screenshot.Screenshot,androidx.test.runner.screenshot.Screenshot +android.support.test.runner.screenshot.TakeScreenshotCallable,androidx.test.runner.screenshot.TakeScreenshotCallable +android.support.test.runner.screenshot.UiAutomationWrapper,androidx.test.runner.screenshot.UiAutomationWrapper +android.support.test.runner.UsageTrackerFacilitator,androidx.test.runner.UsageTrackerFacilitator +android.support.test.uiautomator.AccessibilityNodeInfoDumper,androidx.test.uiautomator.AccessibilityNodeInfoDumper +android.support.test.uiautomator.AccessibilityNodeInfoHelper,androidx.test.uiautomator.AccessibilityNodeInfoHelper +android.support.test.uiautomator.By,androidx.test.uiautomator.By +android.support.test.uiautomator.ByMatcher,androidx.test.uiautomator.ByMatcher +android.support.test.uiautomator.BySelector,androidx.test.uiautomator.BySelector +android.support.test.uiautomator.Condition,androidx.test.uiautomator.Condition +android.support.test.uiautomator.Configurator,androidx.test.uiautomator.Configurator +android.support.test.uiautomator.Direction,androidx.test.uiautomator.Direction +android.support.test.uiautomator.EventCondition,androidx.test.uiautomator.EventCondition +android.support.test.uiautomator.GestureController,androidx.test.uiautomator.GestureController +android.support.test.uiautomator.Gestures,androidx.test.uiautomator.Gestures +android.support.test.uiautomator.IAutomationSupport,androidx.test.uiautomator.IAutomationSupport +android.support.test.uiautomator.InstrumentationAutomationSupport,androidx.test.uiautomator.InstrumentationAutomationSupport +android.support.test.uiautomator.InteractionController,androidx.test.uiautomator.InteractionController +android.support.test.uiautomator.PointerGesture,androidx.test.uiautomator.PointerGesture +android.support.test.uiautomator.QueryController,androidx.test.uiautomator.QueryController +android.support.test.uiautomator.Searchable,androidx.test.uiautomator.Searchable +android.support.test.uiautomator.SearchCondition,androidx.test.uiautomator.SearchCondition +android.support.test.uiautomator.StaleObjectException,androidx.test.uiautomator.StaleObjectException +android.support.test.uiautomator.Tracer,androidx.test.uiautomator.Tracer +android.support.test.uiautomator.UiAutomatorInstrumentationTestRunner,androidx.test.uiautomator.UiAutomatorInstrumentationTestRunner +android.support.test.uiautomator.UiAutomatorTestCase,androidx.test.uiautomator.UiAutomatorTestCase +android.support.test.uiautomator.UiCollection,androidx.test.uiautomator.UiCollection +android.support.test.uiautomator.UiDevice,androidx.test.uiautomator.UiDevice +android.support.test.uiautomator.UiObject,androidx.test.uiautomator.UiObject +android.support.test.uiautomator.UiObject2,androidx.test.uiautomator.UiObject2 +android.support.test.uiautomator.UiObject2Condition,androidx.test.uiautomator.UiObject2Condition +android.support.test.uiautomator.UiObjectNotFoundException,androidx.test.uiautomator.UiObjectNotFoundException +android.support.test.uiautomator.UiScrollable,androidx.test.uiautomator.UiScrollable +android.support.test.uiautomator.UiSelector,androidx.test.uiautomator.UiSelector +android.support.test.uiautomator.UiWatcher,androidx.test.uiautomator.UiWatcher +android.support.test.uiautomator.Until,androidx.test.uiautomator.Until +android.support.test.uiautomator.WaitMixin,androidx.test.uiautomator.WaitMixin +android.support.text.emoji.bundled.BundledEmojiCompatConfig,androidx.emoji.bundled.BundledEmojiCompatConfig +android.support.text.emoji.EmojiCompat,androidx.emoji.text.EmojiCompat +android.support.text.emoji.EmojiMetadata,androidx.emoji.text.EmojiMetadata +android.support.text.emoji.EmojiProcessor,androidx.emoji.text.EmojiProcessor +android.support.text.emoji.EmojiSpan,androidx.emoji.text.EmojiSpan +android.support.text.emoji.FontRequestEmojiCompatConfig,androidx.emoji.text.FontRequestEmojiCompatConfig +android.support.text.emoji.MetadataListReader,androidx.emoji.text.MetadataListReader +android.support.text.emoji.MetadataRepo,androidx.emoji.text.MetadataRepo +android.support.text.emoji.R,androidx.emoji.R +android.support.text.emoji.TypefaceEmojiSpan,androidx.emoji.text.TypefaceEmojiSpan +android.support.text.emoji.widget.EditTextAttributeHelper,androidx.emoji.widget.EditTextAttributeHelper +android.support.text.emoji.widget.EmojiAppCompatButton,androidx.emoji.widget.EmojiAppCompatButton +android.support.text.emoji.widget.EmojiAppCompatEditText,androidx.emoji.widget.EmojiAppCompatEditText +android.support.text.emoji.widget.EmojiAppCompatTextView,androidx.emoji.widget.EmojiAppCompatTextView +android.support.text.emoji.widget.EmojiButton,androidx.emoji.widget.EmojiButton +android.support.text.emoji.widget.EmojiEditableFactory,androidx.emoji.widget.EmojiEditableFactory +android.support.text.emoji.widget.EmojiEditText,androidx.emoji.widget.EmojiEditText +android.support.text.emoji.widget.EmojiEditTextHelper,androidx.emoji.widget.EmojiEditTextHelper +android.support.text.emoji.widget.EmojiExtractEditText,androidx.emoji.widget.EmojiExtractEditText +android.support.text.emoji.widget.EmojiExtractTextLayout,androidx.emoji.widget.EmojiExtractTextLayout +android.support.text.emoji.widget.EmojiInputConnection,androidx.emoji.widget.EmojiInputConnection +android.support.text.emoji.widget.EmojiInputFilter,androidx.emoji.widget.EmojiInputFilter +android.support.text.emoji.widget.EmojiKeyListener,androidx.emoji.widget.EmojiKeyListener +android.support.text.emoji.widget.EmojiTextView,androidx.emoji.widget.EmojiTextView +android.support.text.emoji.widget.EmojiTextViewHelper,androidx.emoji.widget.EmojiTextViewHelper +android.support.text.emoji.widget.EmojiTextWatcher,androidx.emoji.widget.EmojiTextWatcher +android.support.text.emoji.widget.EmojiTransformationMethod,androidx.emoji.widget.EmojiTransformationMethod +android.support.text.emoji.widget.ExtractButtonCompat,androidx.emoji.widget.ExtractButtonCompat +android.support.text.emoji.widget.SpannableBuilder,androidx.emoji.widget.SpannableBuilder +android.support.transition.AnimatorUtils,androidx.transition.AnimatorUtils +android.support.transition.ArcMotion,androidx.transition.ArcMotion +android.support.transition.AutoTransition,androidx.transition.AutoTransition +android.support.transition.ChangeBounds,androidx.transition.ChangeBounds +android.support.transition.ChangeClipBounds,androidx.transition.ChangeClipBounds +android.support.transition.ChangeImageTransform,androidx.transition.ChangeImageTransform +android.support.transition.ChangeScroll,androidx.transition.ChangeScroll +android.support.transition.ChangeTransform,androidx.transition.ChangeTransform +android.support.transition.CircularPropagation,androidx.transition.CircularPropagation +android.support.transition.Explode,androidx.transition.Explode +android.support.transition.Fade,androidx.transition.Fade +android.support.transition.FloatArrayEvaluator,androidx.transition.FloatArrayEvaluator +android.support.transition.FragmentTransitionSupport,androidx.transition.FragmentTransitionSupport +android.support.transition.GhostViewApi14,androidx.transition.GhostViewApi14 +android.support.transition.GhostViewApi21,androidx.transition.GhostViewApi21 +android.support.transition.GhostViewImpl,androidx.transition.GhostViewImpl +android.support.transition.GhostViewUtils,androidx.transition.GhostViewUtils +android.support.transition.ImageViewUtils,androidx.transition.ImageViewUtils +android.support.transition.MatrixUtils,androidx.transition.MatrixUtils +android.support.transition.ObjectAnimatorUtils,androidx.transition.ObjectAnimatorUtils +android.support.transition.PathMotion,androidx.transition.PathMotion +android.support.transition.PathProperty,androidx.transition.PathProperty +android.support.transition.PatternPathMotion,androidx.transition.PatternPathMotion +android.support.transition.PropertyValuesHolderUtils,androidx.transition.PropertyValuesHolderUtils +android.support.transition.R,androidx.transition.R +android.support.transition.RectEvaluator,androidx.transition.RectEvaluator +android.support.transition.Scene,androidx.transition.Scene +android.support.transition.SidePropagation,androidx.transition.SidePropagation +android.support.transition.Slide,androidx.transition.Slide +android.support.transition.Styleable,androidx.transition.Styleable +android.support.transition.Transition,androidx.transition.Transition +android.support.transition.TransitionInflater,androidx.transition.TransitionInflater +android.support.transition.TransitionListenerAdapter,androidx.transition.TransitionListenerAdapter +android.support.transition.TransitionManager,androidx.transition.TransitionManager +android.support.transition.TransitionPropagation,androidx.transition.TransitionPropagation +android.support.transition.TransitionSet,androidx.transition.TransitionSet +android.support.transition.TransitionUtils,androidx.transition.TransitionUtils +android.support.transition.TransitionValues,androidx.transition.TransitionValues +android.support.transition.TransitionValuesMaps,androidx.transition.TransitionValuesMaps +android.support.transition.TranslationAnimationCreator,androidx.transition.TranslationAnimationCreator +android.support.transition.ViewGroupOverlayApi14,androidx.transition.ViewGroupOverlayApi14 +android.support.transition.ViewGroupOverlayApi18,androidx.transition.ViewGroupOverlayApi18 +android.support.transition.ViewGroupOverlayImpl,androidx.transition.ViewGroupOverlayImpl +android.support.transition.ViewGroupUtils,androidx.transition.ViewGroupUtils +android.support.transition.ViewGroupUtilsApi14,androidx.transition.ViewGroupUtilsApi14 +android.support.transition.ViewGroupUtilsApi18,androidx.transition.ViewGroupUtilsApi18 +android.support.transition.ViewOverlayApi14,androidx.transition.ViewOverlayApi14 +android.support.transition.ViewOverlayApi18,androidx.transition.ViewOverlayApi18 +android.support.transition.ViewOverlayImpl,androidx.transition.ViewOverlayImpl +android.support.transition.ViewUtils,androidx.transition.ViewUtils +android.support.transition.ViewUtilsApi19,androidx.transition.ViewUtilsApi19 +android.support.transition.ViewUtilsApi21,androidx.transition.ViewUtilsApi21 +android.support.transition.ViewUtilsApi22,androidx.transition.ViewUtilsApi22 +android.support.transition.ViewUtilsBase,androidx.transition.ViewUtilsBase +android.support.transition.Visibility,androidx.transition.Visibility +android.support.transition.VisibilityPropagation,androidx.transition.VisibilityPropagation +android.support.transition.WindowIdApi14,androidx.transition.WindowIdApi14 +android.support.transition.WindowIdApi18,androidx.transition.WindowIdApi18 +android.support.transition.WindowIdImpl,androidx.transition.WindowIdImpl +android.support.v13.app.ActivityCompat,androidx.legacy.app.ActivityCompat +android.support.v13.app.FragmentCompat,androidx.legacy.app.FragmentCompat +android.support.v13.app.FragmentPagerAdapter,androidx.legacy.app.FragmentPagerAdapter +android.support.v13.app.FragmentStatePagerAdapter,androidx.legacy.app.FragmentStatePagerAdapter +android.support.v13.app.FragmentTabHost,androidx.legacy.app.FragmentTabHost +android.support.v13.view.DragAndDropPermissionsCompat,androidx.core.view.DragAndDropPermissionsCompat +android.support.v13.view.DragStartHelper,androidx.core.view.DragStartHelper +android.support.v13.view.inputmethod.EditorInfoCompat,androidx.core.view.inputmethod.EditorInfoCompat +android.support.v13.view.inputmethod.InputConnectionCompat,androidx.core.view.inputmethod.InputConnectionCompat +android.support.v13.view.inputmethod.InputContentInfoCompat,androidx.core.view.inputmethod.InputContentInfoCompat +android.support.v13.view.ViewCompat,androidx.legacy.view.ViewCompat +android.support.v14.preference.EditTextPreferenceDialogFragment,androidx.preference.EditTextPreferenceDialogFragment +android.support.v14.preference.ListPreferenceDialogFragment,androidx.preference.ListPreferenceDialogFragment +android.support.v14.preference.MultiSelectListPreference,androidx.preference.MultiSelectListPreference +android.support.v14.preference.MultiSelectListPreferenceDialogFragment,androidx.preference.MultiSelectListPreferenceDialogFragment +android.support.v14.preference.PreferenceDialogFragment,androidx.preference.PreferenceDialogFragment +android.support.v14.preference.PreferenceFragment,androidx.preference.PreferenceFragment +android.support.v14.preference.SwitchPreference,androidx.preference.SwitchPreference +android.support.v17.internal.widget.OutlineOnlyWithChildrenFrameLayout,androidx.leanback.preference.internal.OutlineOnlyWithChildrenFrameLayout +android.support.v17.leanback.animation.LogAccelerateInterpolator,androidx.leanback.animation.LogAccelerateInterpolator +android.support.v17.leanback.animation.LogDecelerateInterpolator,androidx.leanback.animation.LogDecelerateInterpolator +android.support.v17.leanback.app.BackgroundFragment,androidx.leanback.app.BackgroundFragment +android.support.v17.leanback.app.BackgroundManager,androidx.leanback.app.BackgroundManager +android.support.v17.leanback.app.BaseFragment,androidx.leanback.app.BaseFragment +android.support.v17.leanback.app.BaseRowFragment,androidx.leanback.app.BaseRowFragment +android.support.v17.leanback.app.BaseRowSupportFragment,androidx.leanback.app.BaseRowSupportFragment +android.support.v17.leanback.app.BaseSupportFragment,androidx.leanback.app.BaseSupportFragment +android.support.v17.leanback.app.BrandedFragment,androidx.leanback.app.BrandedFragment +android.support.v17.leanback.app.BrandedSupportFragment,androidx.leanback.app.BrandedSupportFragment +android.support.v17.leanback.app.BrowseFragment,androidx.leanback.app.BrowseFragment +android.support.v17.leanback.app.BrowseSupportFragment,androidx.leanback.app.BrowseSupportFragment +android.support.v17.leanback.app.DetailsBackgroundVideoHelper,androidx.leanback.app.DetailsBackgroundVideoHelper +android.support.v17.leanback.app.DetailsFragment,androidx.leanback.app.DetailsFragment +android.support.v17.leanback.app.DetailsFragmentBackgroundController,androidx.leanback.app.DetailsFragmentBackgroundController +android.support.v17.leanback.app.DetailsSupportFragment,androidx.leanback.app.DetailsSupportFragment +android.support.v17.leanback.app.DetailsSupportFragmentBackgroundController,androidx.leanback.app.DetailsSupportFragmentBackgroundController +android.support.v17.leanback.app.ErrorFragment,androidx.leanback.app.ErrorFragment +android.support.v17.leanback.app.ErrorSupportFragment,androidx.leanback.app.ErrorSupportFragment +android.support.v17.leanback.app.FragmentUtil,androidx.leanback.app.FragmentUtil +android.support.v17.leanback.app.GuidedStepFragment,androidx.leanback.app.GuidedStepFragment +android.support.v17.leanback.app.GuidedStepRootLayout,androidx.leanback.app.GuidedStepRootLayout +android.support.v17.leanback.app.GuidedStepSupportFragment,androidx.leanback.app.GuidedStepSupportFragment +android.support.v17.leanback.app.HeadersFragment,androidx.leanback.app.HeadersFragment +android.support.v17.leanback.app.HeadersSupportFragment,androidx.leanback.app.HeadersSupportFragment +android.support.v17.leanback.app.ListRowDataAdapter,androidx.leanback.app.ListRowDataAdapter +android.support.v17.leanback.app.OnboardingFragment,androidx.leanback.app.OnboardingFragment +android.support.v17.leanback.app.OnboardingSupportFragment,androidx.leanback.app.OnboardingSupportFragment +android.support.v17.leanback.app.PermissionHelper,androidx.leanback.app.PermissionHelper +android.support.v17.leanback.app.PlaybackFragment,androidx.leanback.app.PlaybackFragment +android.support.v17.leanback.app.PlaybackFragmentGlueHost,androidx.leanback.app.PlaybackFragmentGlueHost +android.support.v17.leanback.app.PlaybackSupportFragment,androidx.leanback.app.PlaybackSupportFragment +android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost,androidx.leanback.app.PlaybackSupportFragmentGlueHost +android.support.v17.leanback.app.ProgressBarManager,androidx.leanback.app.ProgressBarManager +android.support.v17.leanback.app.RowsFragment,androidx.leanback.app.RowsFragment +android.support.v17.leanback.app.RowsSupportFragment,androidx.leanback.app.RowsSupportFragment +android.support.v17.leanback.app.SearchFragment,androidx.leanback.app.SearchFragment +android.support.v17.leanback.app.SearchSupportFragment,androidx.leanback.app.SearchSupportFragment +android.support.v17.leanback.app.VerticalGridFragment,androidx.leanback.app.VerticalGridFragment +android.support.v17.leanback.app.VerticalGridSupportFragment,androidx.leanback.app.VerticalGridSupportFragment +android.support.v17.leanback.app.VideoFragment,androidx.leanback.app.VideoFragment +android.support.v17.leanback.app.VideoFragmentGlueHost,androidx.leanback.app.VideoFragmentGlueHost +android.support.v17.leanback.app.VideoSupportFragment,androidx.leanback.app.VideoSupportFragment +android.support.v17.leanback.app.VideoSupportFragmentGlueHost,androidx.leanback.app.VideoSupportFragmentGlueHost +android.support.v17.leanback.database.CursorMapper,androidx.leanback.database.CursorMapper +android.support.v17.leanback.graphics.BoundsRule,androidx.leanback.graphics.BoundsRule +android.support.v17.leanback.graphics.ColorFilterCache,androidx.leanback.graphics.ColorFilterCache +android.support.v17.leanback.graphics.ColorFilterDimmer,androidx.leanback.graphics.ColorFilterDimmer +android.support.v17.leanback.graphics.ColorOverlayDimmer,androidx.leanback.graphics.ColorOverlayDimmer +android.support.v17.leanback.graphics.CompositeDrawable,androidx.leanback.graphics.CompositeDrawable +android.support.v17.leanback.graphics.FitWidthBitmapDrawable,androidx.leanback.graphics.FitWidthBitmapDrawable +android.support.v17.leanback.media.MediaControllerAdapter,androidx.leanback.media.MediaControllerAdapter +android.support.v17.leanback.media.MediaControllerGlue,androidx.leanback.media.MediaControllerGlue +android.support.v17.leanback.media.MediaPlayerAdapter,androidx.leanback.media.MediaPlayerAdapter +android.support.v17.leanback.media.MediaPlayerGlue,androidx.leanback.media.MediaPlayerGlue +android.support.v17.leanback.media.PlaybackBannerControlGlue,androidx.leanback.media.PlaybackBannerControlGlue +android.support.v17.leanback.media.PlaybackBaseControlGlue,androidx.leanback.media.PlaybackBaseControlGlue +android.support.v17.leanback.media.PlaybackControlGlue,androidx.leanback.media.PlaybackControlGlue +android.support.v17.leanback.media.PlaybackGlue,androidx.leanback.media.PlaybackGlue +android.support.v17.leanback.media.PlaybackGlueHost,androidx.leanback.media.PlaybackGlueHost +android.support.v17.leanback.media.PlaybackTransportControlGlue,androidx.leanback.media.PlaybackTransportControlGlue +android.support.v17.leanback.media.PlayerAdapter,androidx.leanback.media.PlayerAdapter +android.support.v17.leanback.media.SurfaceHolderGlueHost,androidx.leanback.media.SurfaceHolderGlueHost +android.support.v17.leanback.R,androidx.leanback.R +android.support.v17.leanback.system.Settings,androidx.leanback.system.Settings +android.support.v17.leanback.transition.CustomChangeBounds,androidx.leanback.transition.CustomChangeBounds +android.support.v17.leanback.transition.FadeAndShortSlide,androidx.leanback.transition.FadeAndShortSlide +android.support.v17.leanback.transition.LeanbackTransitionHelper,androidx.leanback.transition.LeanbackTransitionHelper +android.support.v17.leanback.transition.ParallaxTransition,androidx.leanback.transition.ParallaxTransition +android.support.v17.leanback.transition.Scale,androidx.leanback.transition.Scale +android.support.v17.leanback.transition.SlideKitkat,androidx.leanback.transition.SlideKitkat +android.support.v17.leanback.transition.SlideNoPropagation,androidx.leanback.transition.SlideNoPropagation +android.support.v17.leanback.transition.TransitionEpicenterCallback,androidx.leanback.transition.TransitionEpicenterCallback +android.support.v17.leanback.transition.TransitionHelper,androidx.leanback.transition.TransitionHelper +android.support.v17.leanback.transition.TransitionListener,androidx.leanback.transition.TransitionListener +android.support.v17.leanback.transition.TranslationAnimationCreator,androidx.leanback.transition.TranslationAnimationCreator +android.support.v17.leanback.util.MathUtil,androidx.leanback.util.MathUtil +android.support.v17.leanback.util.StateMachine,androidx.leanback.util.StateMachine +android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter,androidx.leanback.widget.AbstractDetailsDescriptionPresenter +android.support.v17.leanback.widget.AbstractMediaItemPresenter,androidx.leanback.widget.AbstractMediaItemPresenter +android.support.v17.leanback.widget.AbstractMediaListHeaderPresenter,androidx.leanback.widget.AbstractMediaListHeaderPresenter +android.support.v17.leanback.widget.Action,androidx.leanback.widget.Action +android.support.v17.leanback.widget.ActionPresenterSelector,androidx.leanback.widget.ActionPresenterSelector +android.support.v17.leanback.widget.ArrayObjectAdapter,androidx.leanback.widget.ArrayObjectAdapter +android.support.v17.leanback.widget.BackgroundHelper,androidx.leanback.widget.BackgroundHelper +android.support.v17.leanback.widget.BaseCardView,androidx.leanback.widget.BaseCardView +android.support.v17.leanback.widget.BaseGridView,androidx.leanback.widget.BaseGridView +android.support.v17.leanback.widget.BaseOnItemViewClickedListener,androidx.leanback.widget.BaseOnItemViewClickedListener +android.support.v17.leanback.widget.BaseOnItemViewSelectedListener,androidx.leanback.widget.BaseOnItemViewSelectedListener +android.support.v17.leanback.widget.BrowseFrameLayout,androidx.leanback.widget.BrowseFrameLayout +android.support.v17.leanback.widget.BrowseRowsFrameLayout,androidx.leanback.widget.BrowseRowsFrameLayout +android.support.v17.leanback.widget.CheckableImageView,androidx.leanback.widget.CheckableImageView +android.support.v17.leanback.widget.ClassPresenterSelector,androidx.leanback.widget.ClassPresenterSelector +android.support.v17.leanback.widget.ControlBar,androidx.leanback.widget.ControlBar +android.support.v17.leanback.widget.ControlBarPresenter,androidx.leanback.widget.ControlBarPresenter +android.support.v17.leanback.widget.ControlButtonPresenterSelector,androidx.leanback.widget.ControlButtonPresenterSelector +android.support.v17.leanback.widget.CursorObjectAdapter,androidx.leanback.widget.CursorObjectAdapter +android.support.v17.leanback.widget.DetailsOverviewLogoPresenter,androidx.leanback.widget.DetailsOverviewLogoPresenter +android.support.v17.leanback.widget.DetailsOverviewRow,androidx.leanback.widget.DetailsOverviewRow +android.support.v17.leanback.widget.DetailsOverviewRowPresenter,androidx.leanback.widget.DetailsOverviewRowPresenter +android.support.v17.leanback.widget.DetailsOverviewSharedElementHelper,androidx.leanback.widget.DetailsOverviewSharedElementHelper +android.support.v17.leanback.widget.DetailsParallax,androidx.leanback.widget.DetailsParallax +android.support.v17.leanback.widget.DetailsParallaxDrawable,androidx.leanback.widget.DetailsParallaxDrawable +android.support.v17.leanback.widget.DiffCallback,androidx.leanback.widget.DiffCallback +android.support.v17.leanback.widget.DividerPresenter,androidx.leanback.widget.DividerPresenter +android.support.v17.leanback.widget.DividerRow,androidx.leanback.widget.DividerRow +android.support.v17.leanback.widget.FacetProvider,androidx.leanback.widget.FacetProvider +android.support.v17.leanback.widget.FacetProviderAdapter,androidx.leanback.widget.FacetProviderAdapter +android.support.v17.leanback.widget.FocusHighlight,androidx.leanback.widget.FocusHighlight +android.support.v17.leanback.widget.FocusHighlightHandler,androidx.leanback.widget.FocusHighlightHandler +android.support.v17.leanback.widget.FocusHighlightHelper,androidx.leanback.widget.FocusHighlightHelper +android.support.v17.leanback.widget.ForegroundHelper,androidx.leanback.widget.ForegroundHelper +android.support.v17.leanback.widget.FragmentAnimationProvider,androidx.leanback.widget.FragmentAnimationProvider +android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter,androidx.leanback.widget.FullWidthDetailsOverviewRowPresenter +android.support.v17.leanback.widget.FullWidthDetailsOverviewSharedElementHelper,androidx.leanback.widget.FullWidthDetailsOverviewSharedElementHelper +android.support.v17.leanback.widget.Grid,androidx.leanback.widget.Grid +android.support.v17.leanback.widget.GridLayoutManager,androidx.leanback.widget.GridLayoutManager +android.support.v17.leanback.widget.GuidanceStylingRelativeLayout,androidx.leanback.widget.GuidanceStylingRelativeLayout +android.support.v17.leanback.widget.GuidanceStylist,androidx.leanback.widget.GuidanceStylist +android.support.v17.leanback.widget.GuidedAction,androidx.leanback.widget.GuidedAction +android.support.v17.leanback.widget.GuidedActionAdapter,androidx.leanback.widget.GuidedActionAdapter +android.support.v17.leanback.widget.GuidedActionAdapterGroup,androidx.leanback.widget.GuidedActionAdapterGroup +android.support.v17.leanback.widget.GuidedActionAutofillSupport,androidx.leanback.widget.GuidedActionAutofillSupport +android.support.v17.leanback.widget.GuidedActionDiffCallback,androidx.leanback.widget.GuidedActionDiffCallback +android.support.v17.leanback.widget.GuidedActionEditText,androidx.leanback.widget.GuidedActionEditText +android.support.v17.leanback.widget.GuidedActionItemContainer,androidx.leanback.widget.GuidedActionItemContainer +android.support.v17.leanback.widget.GuidedActionsRelativeLayout,androidx.leanback.widget.GuidedActionsRelativeLayout +android.support.v17.leanback.widget.GuidedActionsStylist,androidx.leanback.widget.GuidedActionsStylist +android.support.v17.leanback.widget.GuidedDatePickerAction,androidx.leanback.widget.GuidedDatePickerAction +android.support.v17.leanback.widget.HeaderItem,androidx.leanback.widget.HeaderItem +android.support.v17.leanback.widget.HorizontalGridView,androidx.leanback.widget.HorizontalGridView +android.support.v17.leanback.widget.HorizontalHoverCardSwitcher,androidx.leanback.widget.HorizontalHoverCardSwitcher +android.support.v17.leanback.widget.ImageCardView,androidx.leanback.widget.ImageCardView +android.support.v17.leanback.widget.ImeKeyMonitor,androidx.leanback.widget.ImeKeyMonitor +android.support.v17.leanback.widget.InvisibleRowPresenter,androidx.leanback.widget.InvisibleRowPresenter +android.support.v17.leanback.widget.ItemAlignment,androidx.leanback.widget.ItemAlignment +android.support.v17.leanback.widget.ItemAlignmentFacet,androidx.leanback.widget.ItemAlignmentFacet +android.support.v17.leanback.widget.ItemAlignmentFacetHelper,androidx.leanback.widget.ItemAlignmentFacetHelper +android.support.v17.leanback.widget.ItemBridgeAdapter,androidx.leanback.widget.ItemBridgeAdapter +android.support.v17.leanback.widget.ItemBridgeAdapterShadowOverlayWrapper,androidx.leanback.widget.ItemBridgeAdapterShadowOverlayWrapper +android.support.v17.leanback.widget.ListRow,androidx.leanback.widget.ListRow +android.support.v17.leanback.widget.ListRowHoverCardView,androidx.leanback.widget.ListRowHoverCardView +android.support.v17.leanback.widget.ListRowPresenter,androidx.leanback.widget.ListRowPresenter +android.support.v17.leanback.widget.ListRowView,androidx.leanback.widget.ListRowView +android.support.v17.leanback.widget.MediaItemActionPresenter,androidx.leanback.widget.MediaItemActionPresenter +android.support.v17.leanback.widget.MediaNowPlayingView,androidx.leanback.widget.MediaNowPlayingView +android.support.v17.leanback.widget.MediaRowFocusView,androidx.leanback.widget.MediaRowFocusView +android.support.v17.leanback.widget.MultiActionsProvider,androidx.leanback.widget.MultiActionsProvider +android.support.v17.leanback.widget.NonOverlappingFrameLayout,androidx.leanback.widget.NonOverlappingFrameLayout +android.support.v17.leanback.widget.NonOverlappingLinearLayout,androidx.leanback.widget.NonOverlappingLinearLayout +android.support.v17.leanback.widget.NonOverlappingLinearLayoutWithForeground,androidx.leanback.widget.NonOverlappingLinearLayoutWithForeground +android.support.v17.leanback.widget.NonOverlappingRelativeLayout,androidx.leanback.widget.NonOverlappingRelativeLayout +android.support.v17.leanback.widget.NonOverlappingView,androidx.leanback.widget.NonOverlappingView +android.support.v17.leanback.widget.ObjectAdapter,androidx.leanback.widget.ObjectAdapter +android.support.v17.leanback.widget.OnActionClickedListener,androidx.leanback.widget.OnActionClickedListener +android.support.v17.leanback.widget.OnChildLaidOutListener,androidx.leanback.widget.OnChildLaidOutListener +android.support.v17.leanback.widget.OnChildSelectedListener,androidx.leanback.widget.OnChildSelectedListener +android.support.v17.leanback.widget.OnChildViewHolderSelectedListener,androidx.leanback.widget.OnChildViewHolderSelectedListener +android.support.v17.leanback.widget.OnItemViewClickedListener,androidx.leanback.widget.OnItemViewClickedListener +android.support.v17.leanback.widget.OnItemViewSelectedListener,androidx.leanback.widget.OnItemViewSelectedListener +android.support.v17.leanback.widget.PageRow,androidx.leanback.widget.PageRow +android.support.v17.leanback.widget.PagingIndicator,androidx.leanback.widget.PagingIndicator +android.support.v17.leanback.widget.Parallax,androidx.leanback.widget.Parallax +android.support.v17.leanback.widget.ParallaxEffect,androidx.leanback.widget.ParallaxEffect +android.support.v17.leanback.widget.ParallaxTarget,androidx.leanback.widget.ParallaxTarget +android.support.v17.leanback.widget.PersistentFocusWrapper,androidx.leanback.widget.PersistentFocusWrapper +android.support.v17.leanback.widget.picker.DatePicker,androidx.leanback.widget.picker.DatePicker +android.support.v17.leanback.widget.picker.Picker,androidx.leanback.widget.picker.Picker +android.support.v17.leanback.widget.picker.PickerColumn,androidx.leanback.widget.picker.PickerColumn +android.support.v17.leanback.widget.picker.PickerUtility,androidx.leanback.widget.picker.PickerUtility +android.support.v17.leanback.widget.picker.TimePicker,androidx.leanback.widget.picker.TimePicker +android.support.v17.leanback.widget.PlaybackControlsPresenter,androidx.leanback.widget.PlaybackControlsPresenter +android.support.v17.leanback.widget.PlaybackControlsRow,androidx.leanback.widget.PlaybackControlsRow +android.support.v17.leanback.widget.PlaybackControlsRowPresenter,androidx.leanback.widget.PlaybackControlsRowPresenter +android.support.v17.leanback.widget.PlaybackControlsRowView,androidx.leanback.widget.PlaybackControlsRowView +android.support.v17.leanback.widget.PlaybackRowPresenter,androidx.leanback.widget.PlaybackRowPresenter +android.support.v17.leanback.widget.PlaybackSeekDataProvider,androidx.leanback.widget.PlaybackSeekDataProvider +android.support.v17.leanback.widget.PlaybackSeekUi,androidx.leanback.widget.PlaybackSeekUi +android.support.v17.leanback.widget.PlaybackTransportRowPresenter,androidx.leanback.widget.PlaybackTransportRowPresenter +android.support.v17.leanback.widget.PlaybackTransportRowView,androidx.leanback.widget.PlaybackTransportRowView +android.support.v17.leanback.widget.Presenter,androidx.leanback.widget.Presenter +android.support.v17.leanback.widget.PresenterSelector,androidx.leanback.widget.PresenterSelector +android.support.v17.leanback.widget.PresenterSwitcher,androidx.leanback.widget.PresenterSwitcher +android.support.v17.leanback.widget.RecyclerViewParallax,androidx.leanback.widget.RecyclerViewParallax +android.support.v17.leanback.widget.ResizingTextView,androidx.leanback.widget.ResizingTextView +android.support.v17.leanback.widget.RoundedRectHelper,androidx.leanback.widget.RoundedRectHelper +android.support.v17.leanback.widget.RoundedRectHelperApi21,androidx.leanback.widget.RoundedRectHelperApi21 +android.support.v17.leanback.widget.Row,androidx.leanback.widget.Row +android.support.v17.leanback.widget.RowContainerView,androidx.leanback.widget.RowContainerView +android.support.v17.leanback.widget.RowHeaderPresenter,androidx.leanback.widget.RowHeaderPresenter +android.support.v17.leanback.widget.RowHeaderView,androidx.leanback.widget.RowHeaderView +android.support.v17.leanback.widget.RowPresenter,androidx.leanback.widget.RowPresenter +android.support.v17.leanback.widget.ScaleFrameLayout,androidx.leanback.widget.ScaleFrameLayout +android.support.v17.leanback.widget.SearchBar,androidx.leanback.widget.SearchBar +android.support.v17.leanback.widget.SearchEditText,androidx.leanback.widget.SearchEditText +android.support.v17.leanback.widget.SearchOrbView,androidx.leanback.widget.SearchOrbView +android.support.v17.leanback.widget.SectionRow,androidx.leanback.widget.SectionRow +android.support.v17.leanback.widget.SeekBar,androidx.leanback.widget.SeekBar +android.support.v17.leanback.widget.ShadowHelper,androidx.leanback.widget.ShadowHelper +android.support.v17.leanback.widget.ShadowHelperApi21,androidx.leanback.widget.ShadowHelperApi21 +android.support.v17.leanback.widget.ShadowOverlayContainer,androidx.leanback.widget.ShadowOverlayContainer +android.support.v17.leanback.widget.ShadowOverlayHelper,androidx.leanback.widget.ShadowOverlayHelper +android.support.v17.leanback.widget.SinglePresenterSelector,androidx.leanback.widget.SinglePresenterSelector +android.support.v17.leanback.widget.SingleRow,androidx.leanback.widget.SingleRow +android.support.v17.leanback.widget.SparseArrayObjectAdapter,androidx.leanback.widget.SparseArrayObjectAdapter +android.support.v17.leanback.widget.SpeechOrbView,androidx.leanback.widget.SpeechOrbView +android.support.v17.leanback.widget.SpeechRecognitionCallback,androidx.leanback.widget.SpeechRecognitionCallback +android.support.v17.leanback.widget.StaggeredGrid,androidx.leanback.widget.StaggeredGrid +android.support.v17.leanback.widget.StaggeredGridDefault,androidx.leanback.widget.StaggeredGridDefault +android.support.v17.leanback.widget.StaticShadowHelper,androidx.leanback.widget.StaticShadowHelper +android.support.v17.leanback.widget.StreamingTextView,androidx.leanback.widget.StreamingTextView +android.support.v17.leanback.widget.ThumbsBar,androidx.leanback.widget.ThumbsBar +android.support.v17.leanback.widget.TitleHelper,androidx.leanback.widget.TitleHelper +android.support.v17.leanback.widget.TitleView,androidx.leanback.widget.TitleView +android.support.v17.leanback.widget.TitleViewAdapter,androidx.leanback.widget.TitleViewAdapter +android.support.v17.leanback.widget.Util,androidx.leanback.widget.Util +android.support.v17.leanback.widget.VerticalGridPresenter,androidx.leanback.widget.VerticalGridPresenter +android.support.v17.leanback.widget.VerticalGridView,androidx.leanback.widget.VerticalGridView +android.support.v17.leanback.widget.VideoSurfaceView,androidx.leanback.widget.VideoSurfaceView +android.support.v17.leanback.widget.ViewHolderTask,androidx.leanback.widget.ViewHolderTask +android.support.v17.leanback.widget.ViewsStateBundle,androidx.leanback.widget.ViewsStateBundle +android.support.v17.leanback.widget.Visibility,androidx.leanback.widget.Visibility +android.support.v17.leanback.widget.WindowAlignment,androidx.leanback.widget.WindowAlignment +android.support.v17.preference.BaseLeanbackPreferenceFragment,androidx.leanback.preference.BaseLeanbackPreferenceFragment +android.support.v17.preference.LeanbackListPreferenceDialogFragment,androidx.leanback.preference.LeanbackListPreferenceDialogFragment +android.support.v17.preference.LeanbackPreferenceDialogFragment,androidx.leanback.preference.LeanbackPreferenceDialogFragment +android.support.v17.preference.LeanbackPreferenceFragment,androidx.leanback.preference.LeanbackPreferenceFragment +android.support.v17.preference.LeanbackPreferenceFragmentTransitionHelperApi21,androidx.leanback.preference.LeanbackPreferenceFragmentTransitionHelperApi21 +android.support.v17.preference.LeanbackSettingsFragment,androidx.leanback.preference.LeanbackSettingsFragment +android.support.v17.preference.LeanbackSettingsRootView,androidx.leanback.preference.LeanbackSettingsRootView +android.support.v17.preference.R,androidx.leanback.preference.R +android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat,androidx.core.accessibilityservice.AccessibilityServiceInfoCompat +android.support.v4.app.ActionBarDrawerToggle,androidx.legacy.app.ActionBarDrawerToggle +android.support.v4.app.ActivityCompat,androidx.core.app.ActivityCompat +android.support.v4.app.ActivityManagerCompat,androidx.core.app.ActivityManagerCompat +android.support.v4.app.ActivityOptionsCompat,androidx.core.app.ActivityOptionsCompat +android.support.v4.app.AlarmManagerCompat,androidx.core.app.AlarmManagerCompat +android.support.v4.app.AppComponentFactory,androidx.core.app.AppComponentFactory +android.support.v4.app.AppLaunchChecker,androidx.core.app.AppLaunchChecker +android.support.v4.app.AppOpsManagerCompat,androidx.core.app.AppOpsManagerCompat +android.support.v4.app.BackStackRecord,androidx.fragment.app.BackStackRecord +android.support.v4.app.BackStackState,androidx.fragment.app.BackStackState +android.support.v4.app.BundleCompat,androidx.core.app.BundleCompat +android.support.v4.app.CoreComponentFactory,androidx.core.app.CoreComponentFactory +android.support.v4.app.DialogFragment,androidx.fragment.app.DialogFragment +android.support.v4.app.Fragment,androidx.fragment.app.Fragment +android.support.v4.app.FragmentActivity,androidx.fragment.app.FragmentActivity +android.support.v4.app.FragmentContainer,androidx.fragment.app.FragmentContainer +android.support.v4.app.FragmentController,androidx.fragment.app.FragmentController +android.support.v4.app.FragmentHostCallback,androidx.fragment.app.FragmentHostCallback +android.support.v4.app.FragmentManager,androidx.fragment.app.FragmentManager +android.support.v4.app.FragmentManagerImpl,androidx.fragment.app.FragmentManagerImpl +android.support.v4.app.FragmentManagerNonConfig,androidx.fragment.app.FragmentManagerNonConfig +android.support.v4.app.FragmentManagerState,androidx.fragment.app.FragmentManagerState +android.support.v4.app.FragmentPagerAdapter,androidx.fragment.app.FragmentPagerAdapter +android.support.v4.app.FragmentState,androidx.fragment.app.FragmentState +android.support.v4.app.FragmentStatePagerAdapter,androidx.fragment.app.FragmentStatePagerAdapter +android.support.v4.app.FragmentTabHost,androidx.fragment.app.FragmentTabHost +android.support.v4.app.FragmentTransaction,androidx.fragment.app.FragmentTransaction +android.support.v4.app.FragmentTransition,androidx.fragment.app.FragmentTransition +android.support.v4.app.FragmentTransitionCompat21,androidx.fragment.app.FragmentTransitionCompat21 +android.support.v4.app.FragmentTransitionImpl,androidx.fragment.app.FragmentTransitionImpl +android.support.v4.app.FrameMetricsAggregator,androidx.core.app.FrameMetricsAggregator +android.support.v4.app.INotificationSideChannel,androidx.core.app.INotificationSideChannel +android.support.v4.app.JobIntentService,androidx.core.app.JobIntentService +android.support.v4.app.ListFragment,androidx.fragment.app.ListFragment +android.support.v4.app.LoaderManager,androidx.loader.app.LoaderManager +android.support.v4.app.LoaderManagerImpl,androidx.loader.app.LoaderManagerImpl +android.support.v4.app.NavUtils,androidx.core.app.NavUtils +android.support.v4.app.NotificationBuilderWithBuilderAccessor,androidx.core.app.NotificationBuilderWithBuilderAccessor +android.support.v4.app.NotificationCompat,androidx.core.app.NotificationCompat +android.support.v4.app.NotificationCompatBuilder,androidx.core.app.NotificationCompatBuilder +android.support.v4.app.NotificationCompatExtras,androidx.core.app.NotificationCompatExtras +android.support.v4.app.NotificationCompatJellybean,androidx.core.app.NotificationCompatJellybean +android.support.v4.app.NotificationCompatSideChannelService,androidx.core.app.NotificationCompatSideChannelService +android.support.v4.app.NotificationManagerCompat,androidx.core.app.NotificationManagerCompat +android.support.v4.app.OneShotPreDrawListener,androidx.fragment.app.OneShotPreDrawListener +android.support.v4.app.Person,androidx.core.app.Person +android.support.v4.app.RemoteInput,androidx.core.app.RemoteInput +android.support.v4.app.ServiceCompat,androidx.core.app.ServiceCompat +android.support.v4.app.ShareCompat,androidx.core.app.ShareCompat +android.support.v4.app.SharedElementCallback,androidx.core.app.SharedElementCallback +android.support.v4.app.SuperNotCalledException,androidx.fragment.app.SuperNotCalledException +android.support.v4.app.SupportActivity,androidx.core.app.ComponentActivity +android.support.v4.app.TaskStackBuilder,androidx.core.app.TaskStackBuilder +android.support.v4.content.AsyncTaskLoader,androidx.loader.content.AsyncTaskLoader +android.support.v4.content.ContentResolverCompat,androidx.core.content.ContentResolverCompat +android.support.v4.content.ContextCompat,androidx.core.content.ContextCompat +android.support.v4.content.CursorLoader,androidx.loader.content.CursorLoader +android.support.v4.content.FileProvider,androidx.core.content.FileProvider +android.support.v4.content.IntentCompat,androidx.core.content.IntentCompat +android.support.v4.content.Loader,androidx.loader.content.Loader +android.support.v4.content.LocalBroadcastManager,androidx.localbroadcastmanager.content.LocalBroadcastManager +android.support.v4.content.MimeTypeFilter,androidx.core.content.MimeTypeFilter +android.support.v4.content.ModernAsyncTask,androidx.loader.content.ModernAsyncTask +android.support.v4.content.PermissionChecker,androidx.core.content.PermissionChecker +android.support.v4.content.pm.ActivityInfoCompat,androidx.core.content.pm.ActivityInfoCompat +android.support.v4.content.pm.PackageInfoCompat,androidx.core.content.pm.PackageInfoCompat +android.support.v4.content.pm.PermissionInfoCompat,androidx.core.content.pm.PermissionInfoCompat +android.support.v4.content.pm.ShortcutInfoCompat,androidx.core.content.pm.ShortcutInfoCompat +android.support.v4.content.pm.ShortcutManagerCompat,androidx.core.content.pm.ShortcutManagerCompat +android.support.v4.content.res.ColorStateListInflaterCompat,androidx.core.content.res.ColorStateListInflaterCompat +android.support.v4.content.res.ComplexColorCompat,androidx.core.content.res.ComplexColorCompat +android.support.v4.content.res.ConfigurationHelper,androidx.core.content.res.ConfigurationHelper +android.support.v4.content.res.FontResourcesParserCompat,androidx.core.content.res.FontResourcesParserCompat +android.support.v4.content.res.GradientColorInflaterCompat,androidx.core.content.res.GradientColorInflaterCompat +android.support.v4.content.res.GrowingArrayUtils,androidx.core.content.res.GrowingArrayUtils +android.support.v4.content.res.ResourcesCompat,androidx.core.content.res.ResourcesCompat +android.support.v4.content.res.TypedArrayUtils,androidx.core.content.res.TypedArrayUtils +android.support.v4.content.SharedPreferencesCompat,androidx.core.content.SharedPreferencesCompat +android.support.v4.content.WakefulBroadcastReceiver,androidx.legacy.content.WakefulBroadcastReceiver +android.support.v4.database.CursorWindowCompat,androidx.core.database.CursorWindowCompat +android.support.v4.database.DatabaseUtilsCompat,androidx.core.database.DatabaseUtilsCompat +android.support.v4.database.sqlite.SQLiteCursorCompat,androidx.core.database.sqlite.SQLiteCursorCompat +android.support.v4.graphics.BitmapCompat,androidx.core.graphics.BitmapCompat +android.support.v4.graphics.ColorUtils,androidx.core.graphics.ColorUtils +android.support.v4.graphics.drawable.DrawableCompat,androidx.core.graphics.drawable.DrawableCompat +android.support.v4.graphics.drawable.IconCompat,androidx.core.graphics.drawable.IconCompat +android.support.v4.graphics.drawable.IconCompatParcelizer,android.support.v4.graphics.drawable.IconCompatParcelizer +android.support.v4.graphics.drawable.RoundedBitmapDrawable,androidx.core.graphics.drawable.RoundedBitmapDrawable +android.support.v4.graphics.drawable.RoundedBitmapDrawable21,androidx.core.graphics.drawable.RoundedBitmapDrawable21 +android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory,androidx.core.graphics.drawable.RoundedBitmapDrawableFactory +android.support.v4.graphics.drawable.TintAwareDrawable,androidx.core.graphics.drawable.TintAwareDrawable +android.support.v4.graphics.drawable.WrappedDrawable,androidx.core.graphics.drawable.WrappedDrawable +android.support.v4.graphics.drawable.WrappedDrawableApi14,androidx.core.graphics.drawable.WrappedDrawableApi14 +android.support.v4.graphics.drawable.WrappedDrawableApi21,androidx.core.graphics.drawable.WrappedDrawableApi21 +android.support.v4.graphics.PaintCompat,androidx.core.graphics.PaintCompat +android.support.v4.graphics.PathParser,androidx.core.graphics.PathParser +android.support.v4.graphics.PathSegment,androidx.core.graphics.PathSegment +android.support.v4.graphics.PathUtils,androidx.core.graphics.PathUtils +android.support.v4.graphics.TypefaceCompat,androidx.core.graphics.TypefaceCompat +android.support.v4.graphics.TypefaceCompatApi21Impl,androidx.core.graphics.TypefaceCompatApi21Impl +android.support.v4.graphics.TypefaceCompatApi24Impl,androidx.core.graphics.TypefaceCompatApi24Impl +android.support.v4.graphics.TypefaceCompatApi26Impl,androidx.core.graphics.TypefaceCompatApi26Impl +android.support.v4.graphics.TypefaceCompatApi28Impl,androidx.core.graphics.TypefaceCompatApi28Impl +android.support.v4.graphics.TypefaceCompatBaseImpl,androidx.core.graphics.TypefaceCompatBaseImpl +android.support.v4.graphics.TypefaceCompatUtil,androidx.core.graphics.TypefaceCompatUtil +android.support.v4.hardware.display.DisplayManagerCompat,androidx.core.hardware.display.DisplayManagerCompat +android.support.v4.hardware.fingerprint.FingerprintManagerCompat,androidx.core.hardware.fingerprint.FingerprintManagerCompat +android.support.v4.internal.view.SupportMenu,androidx.core.internal.view.SupportMenu +android.support.v4.internal.view.SupportMenuItem,androidx.core.internal.view.SupportMenuItem +android.support.v4.internal.view.SupportSubMenu,androidx.core.internal.view.SupportSubMenu +android.support.v4.math.MathUtils,androidx.core.math.MathUtils +android.support.v4.media.app.NotificationCompat,androidx.media.app.NotificationCompat +android.support.v4.media.AudioAttributesCompat,androidx.media.AudioAttributesCompat +android.support.v4.media.AudioAttributesImpl,android.support.v4.media.AudioAttributesImpl +android.support.v4.media.AudioAttributesImplApi21,android.support.v4.media.AudioAttributesImplApi21 +android.support.v4.media.AudioAttributesImplBase,android.support.v4.media.AudioAttributesImplBase +android.support.v4.media.MediaBrowserCompat,android.support.v4.media.MediaBrowserCompat +android.support.v4.media.MediaBrowserCompatApi21,android.support.v4.media.MediaBrowserCompatApi21 +android.support.v4.media.MediaBrowserCompatApi23,android.support.v4.media.MediaBrowserCompatApi23 +android.support.v4.media.MediaBrowserCompatApi26,android.support.v4.media.MediaBrowserCompatApi26 +android.support.v4.media.MediaBrowserCompatUtils,androidx.media.MediaBrowserCompatUtils +android.support.v4.media.MediaBrowserProtocol,androidx.media.MediaBrowserProtocol +android.support.v4.media.MediaBrowserServiceCompat,androidx.media.MediaBrowserServiceCompat +android.support.v4.media.MediaBrowserServiceCompatApi21,androidx.media.MediaBrowserServiceCompatApi21 +android.support.v4.media.MediaBrowserServiceCompatApi23,androidx.media.MediaBrowserServiceCompatApi23 +android.support.v4.media.MediaBrowserServiceCompatApi26,androidx.media.MediaBrowserServiceCompatApi26 +android.support.v4.media.MediaDescriptionCompat,android.support.v4.media.MediaDescriptionCompat +android.support.v4.media.MediaDescriptionCompatApi21,android.support.v4.media.MediaDescriptionCompatApi21 +android.support.v4.media.MediaDescriptionCompatApi23,android.support.v4.media.MediaDescriptionCompatApi23 +android.support.v4.media.MediaMetadataCompat,android.support.v4.media.MediaMetadataCompat +android.support.v4.media.MediaMetadataCompatApi21,android.support.v4.media.MediaMetadataCompatApi21 +android.support.v4.media.MediaSessionManager,android.support.v4.media.MediaSessionManager +android.support.v4.media.MediaSessionManagerImplApi21,android.support.v4.media.MediaSessionManagerImplApi21 +android.support.v4.media.MediaSessionManagerImplApi28,android.support.v4.media.MediaSessionManagerImplApi28 +android.support.v4.media.MediaSessionManagerImplBase,android.support.v4.media.MediaSessionManagerImplBase +android.support.v4.media.ParceledListSliceAdapterApi21,android.support.v4.media.ParceledListSliceAdapterApi21 +android.support.v4.media.RatingCompat,android.support.v4.media.RatingCompat +android.support.v4.media.session.IMediaControllerCallback,android.support.v4.media.session.IMediaControllerCallback +android.support.v4.media.session.IMediaSession,android.support.v4.media.session.IMediaSession +android.support.v4.media.session.MediaButtonReceiver,androidx.media.session.MediaButtonReceiver +android.support.v4.media.session.MediaControllerCompat,android.support.v4.media.session.MediaControllerCompat +android.support.v4.media.session.MediaControllerCompatApi21,android.support.v4.media.session.MediaControllerCompatApi21 +android.support.v4.media.session.MediaControllerCompatApi23,android.support.v4.media.session.MediaControllerCompatApi23 +android.support.v4.media.session.MediaControllerCompatApi24,android.support.v4.media.session.MediaControllerCompatApi24 +android.support.v4.media.session.MediaSessionCompat,android.support.v4.media.session.MediaSessionCompat +android.support.v4.media.session.MediaSessionCompatApi21,android.support.v4.media.session.MediaSessionCompatApi21 +android.support.v4.media.session.MediaSessionCompatApi22,android.support.v4.media.session.MediaSessionCompatApi22 +android.support.v4.media.session.MediaSessionCompatApi23,android.support.v4.media.session.MediaSessionCompatApi23 +android.support.v4.media.session.MediaSessionCompatApi24,android.support.v4.media.session.MediaSessionCompatApi24 +android.support.v4.media.session.ParcelableVolumeInfo,android.support.v4.media.session.ParcelableVolumeInfo +android.support.v4.media.session.PlaybackStateCompat,android.support.v4.media.session.PlaybackStateCompat +android.support.v4.media.session.PlaybackStateCompatApi21,android.support.v4.media.session.PlaybackStateCompatApi21 +android.support.v4.media.session.PlaybackStateCompatApi22,android.support.v4.media.session.PlaybackStateCompatApi22 +android.support.v4.media.VolumeProviderCompat,androidx.media.VolumeProviderCompat +android.support.v4.media.VolumeProviderCompatApi21,androidx.media.VolumeProviderCompatApi21 +android.support.v4.net.ConnectivityManagerCompat,androidx.core.net.ConnectivityManagerCompat +android.support.v4.net.DatagramSocketWrapper,androidx.core.net.DatagramSocketWrapper +android.support.v4.net.TrafficStatsCompat,androidx.core.net.TrafficStatsCompat +android.support.v4.os.BuildCompat,androidx.core.os.BuildCompat +android.support.v4.os.CancellationSignal,androidx.core.os.CancellationSignal +android.support.v4.os.ConfigurationCompat,androidx.core.os.ConfigurationCompat +android.support.v4.os.EnvironmentCompat,androidx.core.os.EnvironmentCompat +android.support.v4.os.HandlerCompat,androidx.core.os.HandlerCompat +android.support.v4.os.IResultReceiver,androidx.core.os.IResultReceiver +android.support.v4.os.LocaleHelper,androidx.core.os.LocaleHelper +android.support.v4.os.LocaleListCompat,androidx.core.os.LocaleListCompat +android.support.v4.os.LocaleListHelper,androidx.core.os.LocaleListHelper +android.support.v4.os.LocaleListInterface,androidx.core.os.LocaleListInterface +android.support.v4.os.OperationCanceledException,androidx.core.os.OperationCanceledException +android.support.v4.os.ParcelableCompat,androidx.core.os.ParcelableCompat +android.support.v4.os.ParcelableCompatCreatorCallbacks,androidx.core.os.ParcelableCompatCreatorCallbacks +android.support.v4.os.ParcelCompat,androidx.core.os.ParcelCompat +android.support.v4.os.ResultReceiver,androidx.core.os.ResultReceiver +android.support.v4.os.TraceCompat,androidx.core.os.TraceCompat +android.support.v4.os.UserManagerCompat,androidx.core.os.UserManagerCompat +android.support.v4.print.PrintHelper,androidx.print.PrintHelper +android.support.v4.provider.DocumentFile,androidx.documentfile.provider.DocumentFile +android.support.v4.provider.DocumentsContractApi19,androidx.documentfile.provider.DocumentsContractApi19 +android.support.v4.provider.FontRequest,androidx.core.provider.FontRequest +android.support.v4.provider.FontsContractCompat,androidx.core.provider.FontsContractCompat +android.support.v4.provider.RawDocumentFile,androidx.documentfile.provider.RawDocumentFile +android.support.v4.provider.SelfDestructiveThread,androidx.core.provider.SelfDestructiveThread +android.support.v4.provider.SingleDocumentFile,androidx.documentfile.provider.SingleDocumentFile +android.support.v4.provider.TreeDocumentFile,androidx.documentfile.provider.TreeDocumentFile +android.support.v4.text.BidiFormatter,androidx.core.text.BidiFormatter +android.support.v4.text.HtmlCompat,androidx.core.text.HtmlCompat +android.support.v4.text.ICUCompat,androidx.core.text.ICUCompat +android.support.v4.text.PrecomputedTextCompat,androidx.core.text.PrecomputedTextCompat +android.support.v4.text.TextDirectionHeuristicCompat,androidx.core.text.TextDirectionHeuristicCompat +android.support.v4.text.TextDirectionHeuristicsCompat,androidx.core.text.TextDirectionHeuristicsCompat +android.support.v4.text.TextUtilsCompat,androidx.core.text.TextUtilsCompat +android.support.v4.text.util.FindAddress,androidx.core.text.util.FindAddress +android.support.v4.text.util.LinkifyCompat,androidx.core.text.util.LinkifyCompat +android.support.v4.util.ArrayMap,androidx.collection.ArrayMap +android.support.v4.util.ArraySet,androidx.collection.ArraySet +android.support.v4.util.AtomicFile,androidx.core.util.AtomicFile +android.support.v4.util.CircularArray,androidx.collection.CircularArray +android.support.v4.util.CircularIntArray,androidx.collection.CircularIntArray +android.support.v4.util.Consumer,androidx.core.util.Consumer +android.support.v4.util.ContainerHelpers,androidx.collection.ContainerHelpers +android.support.v4.util.DebugUtils,androidx.core.util.DebugUtils +android.support.v4.util.LogWriter,androidx.core.util.LogWriter +android.support.v4.util.LongSparseArray,androidx.collection.LongSparseArray +android.support.v4.util.LruCache,androidx.collection.LruCache +android.support.v4.util.MapCollections,androidx.collection.MapCollections +android.support.v4.util.ObjectsCompat,androidx.core.util.ObjectsCompat +android.support.v4.util.Pair,androidx.core.util.Pair +android.support.v4.util.PatternsCompat,androidx.core.util.PatternsCompat +android.support.v4.util.Pools,androidx.core.util.Pools +android.support.v4.util.Preconditions,androidx.core.util.Preconditions +android.support.v4.util.SimpleArrayMap,androidx.collection.SimpleArrayMap +android.support.v4.util.SparseArrayCompat,androidx.collection.SparseArrayCompat +android.support.v4.util.TimeUtils,androidx.core.util.TimeUtils +android.support.v4.view.AbsSavedState,androidx.customview.view.AbsSavedState +android.support.v4.view.accessibility.AccessibilityEventCompat,androidx.core.view.accessibility.AccessibilityEventCompat +android.support.v4.view.accessibility.AccessibilityManagerCompat,androidx.core.view.accessibility.AccessibilityManagerCompat +android.support.v4.view.accessibility.AccessibilityNodeInfoCompat,androidx.core.view.accessibility.AccessibilityNodeInfoCompat +android.support.v4.view.accessibility.AccessibilityNodeProviderCompat,androidx.core.view.accessibility.AccessibilityNodeProviderCompat +android.support.v4.view.accessibility.AccessibilityRecordCompat,androidx.core.view.accessibility.AccessibilityRecordCompat +android.support.v4.view.accessibility.AccessibilityWindowInfoCompat,androidx.core.view.accessibility.AccessibilityWindowInfoCompat +android.support.v4.view.AccessibilityDelegateCompat,androidx.core.view.AccessibilityDelegateCompat +android.support.v4.view.ActionProvider,androidx.core.view.ActionProvider +android.support.v4.view.animation.FastOutLinearInInterpolator,androidx.interpolator.view.animation.FastOutLinearInInterpolator +android.support.v4.view.animation.FastOutSlowInInterpolator,androidx.interpolator.view.animation.FastOutSlowInInterpolator +android.support.v4.view.animation.LinearOutSlowInInterpolator,androidx.interpolator.view.animation.LinearOutSlowInInterpolator +android.support.v4.view.animation.LookupTableInterpolator,androidx.interpolator.view.animation.LookupTableInterpolator +android.support.v4.view.animation.PathInterpolatorApi14,androidx.core.view.animation.PathInterpolatorApi14 +android.support.v4.view.animation.PathInterpolatorCompat,androidx.core.view.animation.PathInterpolatorCompat +android.support.v4.view.AsyncLayoutInflater,androidx.asynclayoutinflater.view.AsyncLayoutInflater +android.support.v4.view.DisplayCutoutCompat,androidx.core.view.DisplayCutoutCompat +android.support.v4.view.GestureDetectorCompat,androidx.core.view.GestureDetectorCompat +android.support.v4.view.GravityCompat,androidx.core.view.GravityCompat +android.support.v4.view.InputDeviceCompat,androidx.core.view.InputDeviceCompat +android.support.v4.view.KeyEventDispatcher,androidx.core.view.KeyEventDispatcher +android.support.v4.view.LayoutInflaterCompat,androidx.core.view.LayoutInflaterCompat +android.support.v4.view.LayoutInflaterFactory,androidx.core.view.LayoutInflaterFactory +android.support.v4.view.MarginLayoutParamsCompat,androidx.core.view.MarginLayoutParamsCompat +android.support.v4.view.MenuCompat,androidx.core.view.MenuCompat +android.support.v4.view.MenuItemCompat,androidx.core.view.MenuItemCompat +android.support.v4.view.MotionEventCompat,androidx.core.view.MotionEventCompat +android.support.v4.view.NestedScrollingChild,androidx.core.view.NestedScrollingChild +android.support.v4.view.NestedScrollingChild2,androidx.core.view.NestedScrollingChild2 +android.support.v4.view.NestedScrollingChildHelper,androidx.core.view.NestedScrollingChildHelper +android.support.v4.view.NestedScrollingParent,androidx.core.view.NestedScrollingParent +android.support.v4.view.NestedScrollingParent2,androidx.core.view.NestedScrollingParent2 +android.support.v4.view.NestedScrollingParentHelper,androidx.core.view.NestedScrollingParentHelper +android.support.v4.view.OnApplyWindowInsetsListener,androidx.core.view.OnApplyWindowInsetsListener +android.support.v4.view.PagerAdapter,androidx.viewpager.widget.PagerAdapter +android.support.v4.view.PagerTabStrip,androidx.viewpager.widget.PagerTabStrip +android.support.v4.view.PagerTitleStrip,androidx.viewpager.widget.PagerTitleStrip +android.support.v4.view.PointerIconCompat,androidx.core.view.PointerIconCompat +android.support.v4.view.ScaleGestureDetectorCompat,androidx.core.view.ScaleGestureDetectorCompat +android.support.v4.view.ScrollingView,androidx.core.view.ScrollingView +android.support.v4.view.TintableBackgroundView,androidx.core.view.TintableBackgroundView +android.support.v4.view.VelocityTrackerCompat,androidx.core.view.VelocityTrackerCompat +android.support.v4.view.ViewCompat,androidx.core.view.ViewCompat +android.support.v4.view.ViewConfigurationCompat,androidx.core.view.ViewConfigurationCompat +android.support.v4.view.ViewGroupCompat,androidx.core.view.ViewGroupCompat +android.support.v4.view.ViewPager,androidx.viewpager.widget.ViewPager +android.support.v4.view.ViewParentCompat,androidx.core.view.ViewParentCompat +android.support.v4.view.ViewPropertyAnimatorCompat,androidx.core.view.ViewPropertyAnimatorCompat +android.support.v4.view.ViewPropertyAnimatorListener,androidx.core.view.ViewPropertyAnimatorListener +android.support.v4.view.ViewPropertyAnimatorListenerAdapter,androidx.core.view.ViewPropertyAnimatorListenerAdapter +android.support.v4.view.ViewPropertyAnimatorUpdateListener,androidx.core.view.ViewPropertyAnimatorUpdateListener +android.support.v4.view.WindowCompat,androidx.core.view.WindowCompat +android.support.v4.view.WindowInsetsCompat,androidx.core.view.WindowInsetsCompat +android.support.v4.widget.AutoScrollHelper,androidx.core.widget.AutoScrollHelper +android.support.v4.widget.AutoSizeableTextView,androidx.core.widget.AutoSizeableTextView +android.support.v4.widget.CircleImageView,androidx.swiperefreshlayout.widget.CircleImageView +android.support.v4.widget.CircularProgressDrawable,androidx.swiperefreshlayout.widget.CircularProgressDrawable +android.support.v4.widget.CompoundButtonCompat,androidx.core.widget.CompoundButtonCompat +android.support.v4.widget.ContentLoadingProgressBar,androidx.core.widget.ContentLoadingProgressBar +android.support.v4.widget.CursorAdapter,androidx.cursoradapter.widget.CursorAdapter +android.support.v4.widget.CursorFilter,androidx.cursoradapter.widget.CursorFilter +android.support.v4.widget.DirectedAcyclicGraph,androidx.coordinatorlayout.widget.DirectedAcyclicGraph +android.support.v4.widget.DrawerLayout,androidx.drawerlayout.widget.DrawerLayout +android.support.v4.widget.EdgeEffectCompat,androidx.core.widget.EdgeEffectCompat +android.support.v4.widget.ExploreByTouchHelper,androidx.customview.widget.ExploreByTouchHelper +android.support.v4.widget.FocusStrategy,androidx.customview.widget.FocusStrategy +android.support.v4.widget.ImageViewCompat,androidx.core.widget.ImageViewCompat +android.support.v4.widget.ListPopupWindowCompat,androidx.core.widget.ListPopupWindowCompat +android.support.v4.widget.ListViewAutoScrollHelper,androidx.core.widget.ListViewAutoScrollHelper +android.support.v4.widget.ListViewCompat,androidx.core.widget.ListViewCompat +android.support.v4.widget.NestedScrollView,androidx.core.widget.NestedScrollView +android.support.v4.widget.PopupMenuCompat,androidx.core.widget.PopupMenuCompat +android.support.v4.widget.PopupWindowCompat,androidx.core.widget.PopupWindowCompat +android.support.v4.widget.ResourceCursorAdapter,androidx.cursoradapter.widget.ResourceCursorAdapter +android.support.v4.widget.ScrollerCompat,androidx.core.widget.ScrollerCompat +android.support.v4.widget.SimpleCursorAdapter,androidx.cursoradapter.widget.SimpleCursorAdapter +android.support.v4.widget.SlidingPaneLayout,androidx.slidingpanelayout.widget.SlidingPaneLayout +android.support.v4.widget.Space,androidx.legacy.widget.Space +android.support.v4.widget.SwipeRefreshLayout,androidx.swiperefreshlayout.widget.SwipeRefreshLayout +android.support.v4.widget.TextViewCompat,androidx.core.widget.TextViewCompat +android.support.v4.widget.TintableCompoundButton,androidx.core.widget.TintableCompoundButton +android.support.v4.widget.TintableImageSourceView,androidx.core.widget.TintableImageSourceView +android.support.v4.widget.ViewDragHelper,androidx.customview.widget.ViewDragHelper +android.support.v4.widget.ViewGroupUtils,androidx.coordinatorlayout.widget.ViewGroupUtils +android.support.v7.app.ActionBar,androidx.appcompat.app.ActionBar +android.support.v7.app.ActionBarDrawerToggle,androidx.appcompat.app.ActionBarDrawerToggle +android.support.v7.app.ActionBarDrawerToggleHoneycomb,androidx.appcompat.app.ActionBarDrawerToggleHoneycomb +android.support.v7.app.AlertController,androidx.appcompat.app.AlertController +android.support.v7.app.AlertDialog,androidx.appcompat.app.AlertDialog +android.support.v7.app.AppCompatActivity,androidx.appcompat.app.AppCompatActivity +android.support.v7.app.AppCompatCallback,androidx.appcompat.app.AppCompatCallback +android.support.v7.app.AppCompatDelegate,androidx.appcompat.app.AppCompatDelegate +android.support.v7.app.AppCompatDelegateImpl,androidx.appcompat.app.AppCompatDelegateImpl +android.support.v7.app.AppCompatDialog,androidx.appcompat.app.AppCompatDialog +android.support.v7.app.AppCompatDialogFragment,androidx.appcompat.app.AppCompatDialogFragment +android.support.v7.app.AppCompatViewInflater,androidx.appcompat.app.AppCompatViewInflater +android.support.v7.app.MediaRouteActionProvider,androidx.mediarouter.app.MediaRouteActionProvider +android.support.v7.app.MediaRouteButton,androidx.mediarouter.app.MediaRouteButton +android.support.v7.app.MediaRouteCastDialog,androidx.mediarouter.app.MediaRouteCastDialog +android.support.v7.app.MediaRouteChooserDialog,androidx.mediarouter.app.MediaRouteChooserDialog +android.support.v7.app.MediaRouteChooserDialogFragment,androidx.mediarouter.app.MediaRouteChooserDialogFragment +android.support.v7.app.MediaRouteControllerDialog,androidx.mediarouter.app.MediaRouteControllerDialog +android.support.v7.app.MediaRouteControllerDialogFragment,androidx.mediarouter.app.MediaRouteControllerDialogFragment +android.support.v7.app.MediaRouteDevicePickerDialog,androidx.mediarouter.app.MediaRouteDevicePickerDialog +android.support.v7.app.MediaRouteDialogFactory,androidx.mediarouter.app.MediaRouteDialogFactory +android.support.v7.app.MediaRouteDialogHelper,androidx.mediarouter.app.MediaRouteDialogHelper +android.support.v7.app.MediaRouteDiscoveryFragment,androidx.mediarouter.app.MediaRouteDiscoveryFragment +android.support.v7.app.MediaRouteExpandCollapseButton,androidx.mediarouter.app.MediaRouteExpandCollapseButton +android.support.v7.app.MediaRouterThemeHelper,androidx.mediarouter.app.MediaRouterThemeHelper +android.support.v7.app.MediaRouteVolumeSlider,androidx.mediarouter.app.MediaRouteVolumeSlider +android.support.v7.app.NavItemSelectedListener,androidx.appcompat.app.NavItemSelectedListener +android.support.v7.app.OverlayListView,androidx.mediarouter.app.OverlayListView +android.support.v7.app.ResourcesFlusher,androidx.appcompat.app.ResourcesFlusher +android.support.v7.app.ToolbarActionBar,androidx.appcompat.app.ToolbarActionBar +android.support.v7.app.TwilightCalculator,androidx.appcompat.app.TwilightCalculator +android.support.v7.app.TwilightManager,androidx.appcompat.app.TwilightManager +android.support.v7.app.WindowDecorActionBar,androidx.appcompat.app.WindowDecorActionBar +android.support.v7.appcompat.R,androidx.appcompat.R +android.support.v7.cardview.R,androidx.cardview.R +android.support.v7.content.res.AppCompatResources,androidx.appcompat.content.res.AppCompatResources +android.support.v7.graphics.ColorCutQuantizer,androidx.palette.graphics.ColorCutQuantizer +android.support.v7.graphics.drawable.AnimatedStateListDrawableCompat,androidx.appcompat.graphics.drawable.AnimatedStateListDrawableCompat +android.support.v7.graphics.drawable.DrawableContainer,androidx.appcompat.graphics.drawable.DrawableContainer +android.support.v7.graphics.drawable.DrawableWrapper,androidx.appcompat.graphics.drawable.DrawableWrapper +android.support.v7.graphics.drawable.DrawerArrowDrawable,androidx.appcompat.graphics.drawable.DrawerArrowDrawable +android.support.v7.graphics.drawable.StateListDrawable,androidx.appcompat.graphics.drawable.StateListDrawable +android.support.v7.graphics.Palette,androidx.palette.graphics.Palette +android.support.v7.graphics.Target,androidx.palette.graphics.Target +android.support.v7.gridlayout.R,androidx.gridlayout.R +android.support.v7.internal.widget.PreferenceImageView,androidx.preference.internal.PreferenceImageView +android.support.v7.media.MediaControlIntent,androidx.mediarouter.media.MediaControlIntent +android.support.v7.media.MediaItemMetadata,androidx.mediarouter.media.MediaItemMetadata +android.support.v7.media.MediaItemStatus,androidx.mediarouter.media.MediaItemStatus +android.support.v7.media.MediaRouteDescriptor,androidx.mediarouter.media.MediaRouteDescriptor +android.support.v7.media.MediaRouteDiscoveryRequest,androidx.mediarouter.media.MediaRouteDiscoveryRequest +android.support.v7.media.MediaRouteProvider,androidx.mediarouter.media.MediaRouteProvider +android.support.v7.media.MediaRouteProviderDescriptor,androidx.mediarouter.media.MediaRouteProviderDescriptor +android.support.v7.media.MediaRouteProviderProtocol,androidx.mediarouter.media.MediaRouteProviderProtocol +android.support.v7.media.MediaRouteProviderService,androidx.mediarouter.media.MediaRouteProviderService +android.support.v7.media.MediaRouter,androidx.mediarouter.media.MediaRouter +android.support.v7.media.MediaRouterApi24,androidx.mediarouter.media.MediaRouterApi24 +android.support.v7.media.MediaRouterJellybean,androidx.mediarouter.media.MediaRouterJellybean +android.support.v7.media.MediaRouterJellybeanMr1,androidx.mediarouter.media.MediaRouterJellybeanMr1 +android.support.v7.media.MediaRouterJellybeanMr2,androidx.mediarouter.media.MediaRouterJellybeanMr2 +android.support.v7.media.MediaRouteSelector,androidx.mediarouter.media.MediaRouteSelector +android.support.v7.media.MediaSessionStatus,androidx.mediarouter.media.MediaSessionStatus +android.support.v7.media.RegisteredMediaRouteProvider,androidx.mediarouter.media.RegisteredMediaRouteProvider +android.support.v7.media.RegisteredMediaRouteProviderWatcher,androidx.mediarouter.media.RegisteredMediaRouteProviderWatcher +android.support.v7.media.RemoteControlClientCompat,androidx.mediarouter.media.RemoteControlClientCompat +android.support.v7.media.RemotePlaybackClient,androidx.mediarouter.media.RemotePlaybackClient +android.support.v7.media.RouteMediaPlayerConnector,androidx.mediarouter.media.RouteMediaPlayerConnector +android.support.v7.media.SystemMediaRouteProvider,androidx.mediarouter.media.SystemMediaRouteProvider +android.support.v7.mediarouter.R,androidx.mediarouter.R +android.support.v7.preference.AndroidResources,androidx.preference.AndroidResources +android.support.v7.preference.CheckBoxPreference,androidx.preference.CheckBoxPreference +android.support.v7.preference.CollapsiblePreferenceGroupController,androidx.preference.CollapsiblePreferenceGroupController +android.support.v7.preference.DialogPreference,androidx.preference.DialogPreference +android.support.v7.preference.DropDownPreference,androidx.preference.DropDownPreference +android.support.v7.preference.EditTextPreference,androidx.preference.EditTextPreference +android.support.v7.preference.EditTextPreferenceDialogFragmentCompat,androidx.preference.EditTextPreferenceDialogFragmentCompat +android.support.v7.preference.internal.AbstractMultiSelectListPreference,androidx.preference.internal.AbstractMultiSelectListPreference +android.support.v7.preference.ListPreference,androidx.preference.ListPreference +android.support.v7.preference.ListPreferenceDialogFragmentCompat,androidx.preference.ListPreferenceDialogFragmentCompat +android.support.v7.preference.MultiSelectListPreferenceDialogFragmentCompat,androidx.preference.MultiSelectListPreferenceDialogFragmentCompat +android.support.v7.preference.Preference,androidx.preference.Preference +android.support.v7.preference.PreferenceCategory,androidx.preference.PreferenceCategory +android.support.v7.preference.PreferenceDataStore,androidx.preference.PreferenceDataStore +android.support.v7.preference.PreferenceDialogFragmentCompat,androidx.preference.PreferenceDialogFragmentCompat +android.support.v7.preference.PreferenceFragmentCompat,androidx.preference.PreferenceFragmentCompat +android.support.v7.preference.PreferenceGroup,androidx.preference.PreferenceGroup +android.support.v7.preference.PreferenceGroupAdapter,androidx.preference.PreferenceGroupAdapter +android.support.v7.preference.PreferenceInflater,androidx.preference.PreferenceInflater +android.support.v7.preference.PreferenceManager,androidx.preference.PreferenceManager +android.support.v7.preference.PreferenceRecyclerViewAccessibilityDelegate,androidx.preference.PreferenceRecyclerViewAccessibilityDelegate +android.support.v7.preference.PreferenceScreen,androidx.preference.PreferenceScreen +android.support.v7.preference.PreferenceViewHolder,androidx.preference.PreferenceViewHolder +android.support.v7.preference.R,androidx.preference.R +android.support.v7.preference.SeekBarPreference,androidx.preference.SeekBarPreference +android.support.v7.preference.SwitchPreferenceCompat,androidx.preference.SwitchPreferenceCompat +android.support.v7.preference.TwoStatePreference,androidx.preference.TwoStatePreference +android.support.v7.preference.UnPressableLinearLayout,androidx.preference.UnPressableLinearLayout +android.support.v7.recyclerview.extensions.AsyncDifferConfig,androidx.recyclerview.widget.AsyncDifferConfig +android.support.v7.recyclerview.extensions.AsyncListDiffer,androidx.recyclerview.widget.AsyncListDiffer +android.support.v7.recyclerview.extensions.ListAdapter,androidx.recyclerview.widget.ListAdapter +android.support.v7.recyclerview.R,androidx.recyclerview.R +android.support.v7.text.AllCapsTransformationMethod,androidx.appcompat.text.AllCapsTransformationMethod +android.support.v7.util.AdapterListUpdateCallback,androidx.recyclerview.widget.AdapterListUpdateCallback +android.support.v7.util.AsyncListUtil,androidx.recyclerview.widget.AsyncListUtil +android.support.v7.util.BatchingListUpdateCallback,androidx.recyclerview.widget.BatchingListUpdateCallback +android.support.v7.util.DiffUtil,androidx.recyclerview.widget.DiffUtil +android.support.v7.util.ListUpdateCallback,androidx.recyclerview.widget.ListUpdateCallback +android.support.v7.util.MessageThreadUtil,androidx.recyclerview.widget.MessageThreadUtil +android.support.v7.util.SortedList,androidx.recyclerview.widget.SortedList +android.support.v7.util.ThreadUtil,androidx.recyclerview.widget.ThreadUtil +android.support.v7.util.TileList,androidx.recyclerview.widget.TileList +android.support.v7.view.ActionBarPolicy,androidx.appcompat.view.ActionBarPolicy +android.support.v7.view.ActionMode,androidx.appcompat.view.ActionMode +android.support.v7.view.CollapsibleActionView,androidx.appcompat.view.CollapsibleActionView +android.support.v7.view.ContextThemeWrapper,androidx.appcompat.view.ContextThemeWrapper +android.support.v7.view.menu.ActionMenuItem,androidx.appcompat.view.menu.ActionMenuItem +android.support.v7.view.menu.ActionMenuItemView,androidx.appcompat.view.menu.ActionMenuItemView +android.support.v7.view.menu.BaseMenuPresenter,androidx.appcompat.view.menu.BaseMenuPresenter +android.support.v7.view.menu.BaseMenuWrapper,androidx.appcompat.view.menu.BaseMenuWrapper +android.support.v7.view.menu.BaseWrapper,androidx.appcompat.view.menu.BaseWrapper +android.support.v7.view.menu.CascadingMenuPopup,androidx.appcompat.view.menu.CascadingMenuPopup +android.support.v7.view.menu.ExpandedMenuView,androidx.appcompat.view.menu.ExpandedMenuView +android.support.v7.view.menu.ListMenuItemView,androidx.appcompat.view.menu.ListMenuItemView +android.support.v7.view.menu.ListMenuPresenter,androidx.appcompat.view.menu.ListMenuPresenter +android.support.v7.view.menu.MenuAdapter,androidx.appcompat.view.menu.MenuAdapter +android.support.v7.view.menu.MenuBuilder,androidx.appcompat.view.menu.MenuBuilder +android.support.v7.view.menu.MenuDialogHelper,androidx.appcompat.view.menu.MenuDialogHelper +android.support.v7.view.menu.MenuHelper,androidx.appcompat.view.menu.MenuHelper +android.support.v7.view.menu.MenuItemImpl,androidx.appcompat.view.menu.MenuItemImpl +android.support.v7.view.menu.MenuItemWrapperICS,androidx.appcompat.view.menu.MenuItemWrapperICS +android.support.v7.view.menu.MenuItemWrapperJB,androidx.appcompat.view.menu.MenuItemWrapperJB +android.support.v7.view.menu.MenuPopup,androidx.appcompat.view.menu.MenuPopup +android.support.v7.view.menu.MenuPopupHelper,androidx.appcompat.view.menu.MenuPopupHelper +android.support.v7.view.menu.MenuPresenter,androidx.appcompat.view.menu.MenuPresenter +android.support.v7.view.menu.MenuView,androidx.appcompat.view.menu.MenuView +android.support.v7.view.menu.MenuWrapperFactory,androidx.appcompat.view.menu.MenuWrapperFactory +android.support.v7.view.menu.MenuWrapperICS,androidx.appcompat.view.menu.MenuWrapperICS +android.support.v7.view.menu.ShowableListMenu,androidx.appcompat.view.menu.ShowableListMenu +android.support.v7.view.menu.StandardMenuPopup,androidx.appcompat.view.menu.StandardMenuPopup +android.support.v7.view.menu.SubMenuBuilder,androidx.appcompat.view.menu.SubMenuBuilder +android.support.v7.view.menu.SubMenuWrapperICS,androidx.appcompat.view.menu.SubMenuWrapperICS +android.support.v7.view.StandaloneActionMode,androidx.appcompat.view.StandaloneActionMode +android.support.v7.view.SupportActionModeWrapper,androidx.appcompat.view.SupportActionModeWrapper +android.support.v7.view.SupportMenuInflater,androidx.appcompat.view.SupportMenuInflater +android.support.v7.view.ViewPropertyAnimatorCompatSet,androidx.appcompat.view.ViewPropertyAnimatorCompatSet +android.support.v7.view.WindowCallbackWrapper,androidx.appcompat.view.WindowCallbackWrapper +android.support.v7.widget.AbsActionBarView,androidx.appcompat.widget.AbsActionBarView +android.support.v7.widget.ActionBarBackgroundDrawable,androidx.appcompat.widget.ActionBarBackgroundDrawable +android.support.v7.widget.ActionBarContainer,androidx.appcompat.widget.ActionBarContainer +android.support.v7.widget.ActionBarContextView,androidx.appcompat.widget.ActionBarContextView +android.support.v7.widget.ActionBarOverlayLayout,androidx.appcompat.widget.ActionBarOverlayLayout +android.support.v7.widget.ActionMenuPresenter,androidx.appcompat.widget.ActionMenuPresenter +android.support.v7.widget.ActionMenuView,androidx.appcompat.widget.ActionMenuView +android.support.v7.widget.ActivityChooserModel,androidx.appcompat.widget.ActivityChooserModel +android.support.v7.widget.ActivityChooserView,androidx.appcompat.widget.ActivityChooserView +android.support.v7.widget.AdapterHelper,androidx.recyclerview.widget.AdapterHelper +android.support.v7.widget.AlertDialogLayout,androidx.appcompat.widget.AlertDialogLayout +android.support.v7.widget.AppCompatAutoCompleteTextView,androidx.appcompat.widget.AppCompatAutoCompleteTextView +android.support.v7.widget.AppCompatBackgroundHelper,androidx.appcompat.widget.AppCompatBackgroundHelper +android.support.v7.widget.AppCompatButton,androidx.appcompat.widget.AppCompatButton +android.support.v7.widget.AppCompatCheckBox,androidx.appcompat.widget.AppCompatCheckBox +android.support.v7.widget.AppCompatCheckedTextView,androidx.appcompat.widget.AppCompatCheckedTextView +android.support.v7.widget.AppCompatCompoundButtonHelper,androidx.appcompat.widget.AppCompatCompoundButtonHelper +android.support.v7.widget.AppCompatDrawableManager,androidx.appcompat.widget.AppCompatDrawableManager +android.support.v7.widget.AppCompatEditText,androidx.appcompat.widget.AppCompatEditText +android.support.v7.widget.AppCompatHintHelper,androidx.appcompat.widget.AppCompatHintHelper +android.support.v7.widget.AppCompatImageButton,androidx.appcompat.widget.AppCompatImageButton +android.support.v7.widget.AppCompatImageHelper,androidx.appcompat.widget.AppCompatImageHelper +android.support.v7.widget.AppCompatImageView,androidx.appcompat.widget.AppCompatImageView +android.support.v7.widget.AppCompatMultiAutoCompleteTextView,androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView +android.support.v7.widget.AppCompatPopupWindow,androidx.appcompat.widget.AppCompatPopupWindow +android.support.v7.widget.AppCompatProgressBarHelper,androidx.appcompat.widget.AppCompatProgressBarHelper +android.support.v7.widget.AppCompatRadioButton,androidx.appcompat.widget.AppCompatRadioButton +android.support.v7.widget.AppCompatRatingBar,androidx.appcompat.widget.AppCompatRatingBar +android.support.v7.widget.AppCompatSeekBar,androidx.appcompat.widget.AppCompatSeekBar +android.support.v7.widget.AppCompatSeekBarHelper,androidx.appcompat.widget.AppCompatSeekBarHelper +android.support.v7.widget.AppCompatSpinner,androidx.appcompat.widget.AppCompatSpinner +android.support.v7.widget.AppCompatTextHelper,androidx.appcompat.widget.AppCompatTextHelper +android.support.v7.widget.AppCompatTextView,androidx.appcompat.widget.AppCompatTextView +android.support.v7.widget.AppCompatTextViewAutoSizeHelper,androidx.appcompat.widget.AppCompatTextViewAutoSizeHelper +android.support.v7.widget.ButtonBarLayout,androidx.appcompat.widget.ButtonBarLayout +android.support.v7.widget.CardView,androidx.cardview.widget.CardView +android.support.v7.widget.CardViewApi17Impl,androidx.cardview.widget.CardViewApi17Impl +android.support.v7.widget.CardViewApi21Impl,androidx.cardview.widget.CardViewApi21Impl +android.support.v7.widget.CardViewBaseImpl,androidx.cardview.widget.CardViewBaseImpl +android.support.v7.widget.CardViewDelegate,androidx.cardview.widget.CardViewDelegate +android.support.v7.widget.CardViewImpl,androidx.cardview.widget.CardViewImpl +android.support.v7.widget.ChildHelper,androidx.recyclerview.widget.ChildHelper +android.support.v7.widget.ContentFrameLayout,androidx.appcompat.widget.ContentFrameLayout +android.support.v7.widget.DecorContentParent,androidx.appcompat.widget.DecorContentParent +android.support.v7.widget.DecorToolbar,androidx.appcompat.widget.DecorToolbar +android.support.v7.widget.DefaultItemAnimator,androidx.recyclerview.widget.DefaultItemAnimator +android.support.v7.widget.DialogTitle,androidx.appcompat.widget.DialogTitle +android.support.v7.widget.DividerItemDecoration,androidx.recyclerview.widget.DividerItemDecoration +android.support.v7.widget.DrawableUtils,androidx.appcompat.widget.DrawableUtils +android.support.v7.widget.DropDownListView,androidx.appcompat.widget.DropDownListView +android.support.v7.widget.FastScroller,androidx.recyclerview.widget.FastScroller +android.support.v7.widget.FitWindowsFrameLayout,androidx.appcompat.widget.FitWindowsFrameLayout +android.support.v7.widget.FitWindowsLinearLayout,androidx.appcompat.widget.FitWindowsLinearLayout +android.support.v7.widget.FitWindowsViewGroup,androidx.appcompat.widget.FitWindowsViewGroup +android.support.v7.widget.ForwardingListener,androidx.appcompat.widget.ForwardingListener +android.support.v7.widget.GapWorker,androidx.recyclerview.widget.GapWorker +android.support.v7.widget.GridLayout,androidx.gridlayout.widget.GridLayout +android.support.v7.widget.GridLayoutManager,androidx.recyclerview.widget.GridLayoutManager +android.support.v7.widget.helper.ItemTouchHelper,androidx.recyclerview.widget.ItemTouchHelper +android.support.v7.widget.helper.ItemTouchUIUtil,androidx.recyclerview.widget.ItemTouchUIUtil +android.support.v7.widget.helper.ItemTouchUIUtilImpl,androidx.recyclerview.widget.ItemTouchUIUtilImpl +android.support.v7.widget.LayoutState,androidx.recyclerview.widget.LayoutState +android.support.v7.widget.LinearLayoutCompat,androidx.appcompat.widget.LinearLayoutCompat +android.support.v7.widget.LinearLayoutManager,androidx.recyclerview.widget.LinearLayoutManager +android.support.v7.widget.LinearSmoothScroller,androidx.recyclerview.widget.LinearSmoothScroller +android.support.v7.widget.LinearSnapHelper,androidx.recyclerview.widget.LinearSnapHelper +android.support.v7.widget.ListPopupWindow,androidx.appcompat.widget.ListPopupWindow +android.support.v7.widget.MenuItemHoverListener,androidx.appcompat.widget.MenuItemHoverListener +android.support.v7.widget.MenuPopupWindow,androidx.appcompat.widget.MenuPopupWindow +android.support.v7.widget.OpReorderer,androidx.recyclerview.widget.OpReorderer +android.support.v7.widget.OrientationHelper,androidx.recyclerview.widget.OrientationHelper +android.support.v7.widget.PagerSnapHelper,androidx.recyclerview.widget.PagerSnapHelper +android.support.v7.widget.PopupMenu,androidx.appcompat.widget.PopupMenu +android.support.v7.widget.RecyclerView,androidx.recyclerview.widget.RecyclerView +android.support.v7.widget.RecyclerViewAccessibilityDelegate,androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate +android.support.v7.widget.ResourcesWrapper,androidx.appcompat.widget.ResourcesWrapper +android.support.v7.widget.RoundRectDrawable,androidx.cardview.widget.RoundRectDrawable +android.support.v7.widget.RoundRectDrawableWithShadow,androidx.cardview.widget.RoundRectDrawableWithShadow +android.support.v7.widget.RtlSpacingHelper,androidx.appcompat.widget.RtlSpacingHelper +android.support.v7.widget.ScrollbarHelper,androidx.recyclerview.widget.ScrollbarHelper +android.support.v7.widget.ScrollingTabContainerView,androidx.appcompat.widget.ScrollingTabContainerView +android.support.v7.widget.SearchView,androidx.appcompat.widget.SearchView +android.support.v7.widget.ShareActionProvider,androidx.appcompat.widget.ShareActionProvider +android.support.v7.widget.SimpleItemAnimator,androidx.recyclerview.widget.SimpleItemAnimator +android.support.v7.widget.SnapHelper,androidx.recyclerview.widget.SnapHelper +android.support.v7.widget.StaggeredGridLayoutManager,androidx.recyclerview.widget.StaggeredGridLayoutManager +android.support.v7.widget.SuggestionsAdapter,androidx.appcompat.widget.SuggestionsAdapter +android.support.v7.widget.SwitchCompat,androidx.appcompat.widget.SwitchCompat +android.support.v7.widget.ThemedSpinnerAdapter,androidx.appcompat.widget.ThemedSpinnerAdapter +android.support.v7.widget.ThemeUtils,androidx.appcompat.widget.ThemeUtils +android.support.v7.widget.TintContextWrapper,androidx.appcompat.widget.TintContextWrapper +android.support.v7.widget.TintInfo,androidx.appcompat.widget.TintInfo +android.support.v7.widget.TintResources,androidx.appcompat.widget.TintResources +android.support.v7.widget.TintTypedArray,androidx.appcompat.widget.TintTypedArray +android.support.v7.widget.Toolbar,androidx.appcompat.widget.Toolbar +android.support.v7.widget.ToolbarWidgetWrapper,androidx.appcompat.widget.ToolbarWidgetWrapper +android.support.v7.widget.TooltipCompat,androidx.appcompat.widget.TooltipCompat +android.support.v7.widget.TooltipCompatHandler,androidx.appcompat.widget.TooltipCompatHandler +android.support.v7.widget.TooltipPopup,androidx.appcompat.widget.TooltipPopup +android.support.v7.widget.util.SortedListAdapterCallback,androidx.recyclerview.widget.SortedListAdapterCallback +android.support.v7.widget.VectorEnabledTintResources,androidx.appcompat.widget.VectorEnabledTintResources +android.support.v7.widget.ViewBoundsCheck,androidx.recyclerview.widget.ViewBoundsCheck +android.support.v7.widget.ViewInfoStore,androidx.recyclerview.widget.ViewInfoStore +android.support.v7.widget.ViewStubCompat,androidx.appcompat.widget.ViewStubCompat +android.support.v7.widget.ViewUtils,androidx.appcompat.widget.ViewUtils +android.support.v7.widget.WithHint,androidx.appcompat.widget.WithHint +android.support.wear.activity.ConfirmationActivity,androidx.wear.activity.ConfirmationActivity +android.support.wear.ambient.AmbientDelegate,androidx.wear.ambient.AmbientDelegate +android.support.wear.ambient.AmbientMode,androidx.wear.ambient.AmbientMode +android.support.wear.ambient.AmbientModeSupport,androidx.wear.ambient.AmbientModeSupport +android.support.wear.ambient.SharedLibraryVersion,androidx.wear.ambient.SharedLibraryVersion +android.support.wear.ambient.WearableControllerProvider,androidx.wear.ambient.WearableControllerProvider +android.support.wear.internal.widget.drawer.MultiPagePresenter,androidx.wear.internal.widget.drawer.MultiPagePresenter +android.support.wear.internal.widget.drawer.MultiPageUi,androidx.wear.internal.widget.drawer.MultiPageUi +android.support.wear.internal.widget.drawer.SinglePagePresenter,androidx.wear.internal.widget.drawer.SinglePagePresenter +android.support.wear.internal.widget.drawer.SinglePageUi,androidx.wear.internal.widget.drawer.SinglePageUi +android.support.wear.internal.widget.drawer.WearableNavigationDrawerPresenter,androidx.wear.internal.widget.drawer.WearableNavigationDrawerPresenter +android.support.wear.internal.widget.ResourcesUtil,androidx.wear.internal.widget.ResourcesUtil +android.support.wear.R,androidx.wear.R +android.support.wear.utils.MetadataConstants,androidx.wear.utils.MetadataConstants +android.support.wear.widget.BezierSCurveInterpolator,androidx.wear.widget.BezierSCurveInterpolator +android.support.wear.widget.BoxInsetLayout,androidx.wear.widget.BoxInsetLayout +android.support.wear.widget.CircledImageView,androidx.wear.widget.CircledImageView +android.support.wear.widget.CircularProgressLayout,androidx.wear.widget.CircularProgressLayout +android.support.wear.widget.CircularProgressLayoutController,androidx.wear.widget.CircularProgressLayoutController +android.support.wear.widget.ConfirmationOverlay,androidx.wear.widget.ConfirmationOverlay +android.support.wear.widget.CurvingLayoutCallback,androidx.wear.widget.CurvingLayoutCallback +android.support.wear.widget.drawer.AbsListViewFlingWatcher,androidx.wear.widget.drawer.AbsListViewFlingWatcher +android.support.wear.widget.drawer.FlingWatcherFactory,androidx.wear.widget.drawer.FlingWatcherFactory +android.support.wear.widget.drawer.NestedScrollViewFlingWatcher,androidx.wear.widget.drawer.NestedScrollViewFlingWatcher +android.support.wear.widget.drawer.PageIndicatorView,androidx.wear.widget.drawer.PageIndicatorView +android.support.wear.widget.drawer.RecyclerViewFlingWatcher,androidx.wear.widget.drawer.RecyclerViewFlingWatcher +android.support.wear.widget.drawer.ScrollViewFlingWatcher,androidx.wear.widget.drawer.ScrollViewFlingWatcher +android.support.wear.widget.drawer.WearableActionDrawerMenu,androidx.wear.widget.drawer.WearableActionDrawerMenu +android.support.wear.widget.drawer.WearableActionDrawerView,androidx.wear.widget.drawer.WearableActionDrawerView +android.support.wear.widget.drawer.WearableDrawerController,androidx.wear.widget.drawer.WearableDrawerController +android.support.wear.widget.drawer.WearableDrawerLayout,androidx.wear.widget.drawer.WearableDrawerLayout +android.support.wear.widget.drawer.WearableDrawerView,androidx.wear.widget.drawer.WearableDrawerView +android.support.wear.widget.drawer.WearableNavigationDrawerView,androidx.wear.widget.drawer.WearableNavigationDrawerView +android.support.wear.widget.ProgressDrawable,androidx.wear.widget.ProgressDrawable +android.support.wear.widget.ResourcesUtil,androidx.wear.widget.ResourcesUtil +android.support.wear.widget.RoundedDrawable,androidx.wear.widget.RoundedDrawable +android.support.wear.widget.ScrollManager,androidx.wear.widget.ScrollManager +android.support.wear.widget.SimpleAnimatorListener,androidx.wear.widget.SimpleAnimatorListener +android.support.wear.widget.SwipeDismissFrameLayout,androidx.wear.widget.SwipeDismissFrameLayout +android.support.wear.widget.SwipeDismissLayout,androidx.wear.widget.SwipeDismissLayout +android.support.wear.widget.WearableLinearLayoutManager,androidx.wear.widget.WearableLinearLayoutManager +android.support.wear.widget.WearableRecyclerView,androidx.wear.widget.WearableRecyclerView diff --git a/app/build.gradle b/app/build.gradle index caf50d0c..95cc84fa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,84 +1,91 @@ apply plugin: 'com.android.application' +//apply plugin: 'com.guardsquare.proguard' +//apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.google.firebase.crashlytics' android { - compileSdkVersion 25 - buildToolsVersion '28.0.3' - + compileSdkVersion 30 defaultConfig { - applicationId 'com.sirkut.blocktopograph' - minSdkVersion 16 - targetSdkVersion 28 - versionCode 10 - versionName "1.7" + applicationId 'rbq2012.blocktopograph' + minSdkVersion 26 + targetSdkVersion 29 + versionCode 1090007 + versionName "1.9.5" + vectorDrawables.useSupportLibrary = true } - def keystorePropertiesFile = rootProject.file("keystore.properties") - def hasKeystore = keystorePropertiesFile.exists() - def keystoreProperties - if(hasKeystore) { - keystoreProperties = new Properties() - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + dataBinding { + enabled true } - - signingConfigs { - if (hasKeystore) { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile rootProject.file(keystoreProperties['storeFile']) - storePassword keystoreProperties['storePassword'] - } - } - config { - keyAlias 'key1' - keyPassword 'keypassword' - storeFile file('/home/alex/Documents/keystore') - storePassword 'keypassword' - } + configurations { + implementation.exclude group: 'org.jetbrains', module: 'annotations' } + buildTypes { - - productFlavors { - if (hasKeystore) { - mainFlavor { - signingConfig signingConfigs.release + debug { + firebaseCrashlytics { + mappingFileUploadEnabled false } - } - } - - buildTypes { - if (hasKeystore) { - release { - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + postprocessing { + removeUnusedCode true + obfuscate false + optimizeCode true + proguardFile 'proguard-rules.pro' } + //multiDexEnabled true + ext.alwaysUpdateBuildId = false } - // opensource { - //minifyEnabled true - //shrinkResources true - // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - //} + release { - signingConfig signingConfigs.config + firebaseCrashlytics { + mappingFileUploadEnabled false + } + postprocessing { + removeUnusedCode true + obfuscate false + optimizeCode true + proguardFile 'proguard-rules.pro' + } +// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } } dependencies { - implementation fileTree(include: ['*.jar', '*.so'], dir: 'libs') - testImplementation 'junit:junit:4.12' - implementation project(':android-leveldb') + implementation fileTree(include: ['*.jar', '*.so', '*.aar'], dir: 'libs') + implementation 'com.google.firebase:firebase-crashlytics:18.2.1' + implementation 'com.google.firebase:firebase-analytics:19.0.0' + testImplementation 'junit:junit:4.13.2' + implementation project(':leveldb') implementation project(':tileview') - implementation 'com.android.support:appcompat-v7:25.4.0' - implementation 'com.android.support:recyclerview-v7:25.4.0' implementation 'com.github.clans:fab:1.6.4' - implementation 'com.android.support:design:25.4.0' - implementation 'com.github.bmelnychuk:atv:1.2.8' + implementation 'com.github.bmelnychuk:atv:1.2.9' + implementation 'com.github.woxthebox:draglistview:1.7.2' + implementation 'com.andreabaccega:android-edittext-validator:1.3.5' //core is the new recommended alias for analytics - implementation 'com.google.firebase:firebase-core:16.0.6' + implementation 'com.google.firebase:firebase-core:19.0.0' + //implementation 'org.jetbrains:annotations-java5:15.0' + implementation 'com.tomergoldst.android:tooltips:1.1.0' + implementation 'androidx.annotation:annotation:1.2.0' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.recyclerview:recyclerview:1.2.1' + implementation 'com.google.android.material:material:1.4.0' + implementation 'com.github.bumptech.glide:glide:4.12.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' + //implementation 'com.github.MikeOrtiz:TouchImageView:2.1.1' + implementation 'com.github.chrisbanes:PhotoView:2.3.0' + implementation 'com.github.florent37:expansionpanel:1.2.4' + implementation 'com.github.jbvincey:nestedradiobutton:1.1' + implementation 'net.lingala.zip4j:zip4j:2.9.0' + // do NOT accidentally "up"-grade to the 2003 version + //noinspection GradleDependency + implementation 'commons-io:commons-io:2.11.0' + implementation 'org.apache.commons:commons-lang3:3.12.0' + //debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.1' + implementation 'com.google.guava:guava:30.1.1-jre' } - -apply plugin: 'com.google.gms.google-services' diff --git a/app/release/output.json b/app/release/output.json deleted file mode 100644 index a14f730e..00000000 --- a/app/release/output.json +++ /dev/null @@ -1 +0,0 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":10},"path":"app-release.apk","properties":{"packageId":"com.mithrilmania.blocktopograph","split":"","minSdkVersion":"16"}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c6a313c1..88a8366f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,62 +6,96 @@ - - + + + + + android:theme="@style/AppTheme" + tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute"> + + + + - + android:theme="@style/AppTheme.NoActionBar"> - - - - - - + android:parentActivityName=".worldlist.WorldItemListActivity" + android:theme="@style/AppTheme.NoActionBar" /> + android:label="@string/title_activity_world" + android:parentActivityName=".worldlist.WorldItemListActivity" + android:theme="@style/World" /> + + + + + + + + + + + + + + + android:value="com.mithrilmania.blocktopograph.WorldActivity" /> + + android:value="28.0.0" + tools:node="replace" /> diff --git a/app/src/main/assets/6394e0cc7cd98d1069b54ffa2c3fb80e7aec9065.jpg b/app/src/main/assets/6394e0cc7cd98d1069b54ffa2c3fb80e7aec9065.jpg new file mode 100644 index 00000000..c70bf949 Binary files /dev/null and b/app/src/main/assets/6394e0cc7cd98d1069b54ffa2c3fb80e7aec9065.jpg differ diff --git a/app/src/main/assets/block_icons.png b/app/src/main/assets/block_icons.png new file mode 100644 index 00000000..2981b187 Binary files /dev/null and b/app/src/main/assets/block_icons.png differ diff --git a/app/src/main/assets/dats/1_2_13-player.dat b/app/src/main/assets/dats/1_2_13-player.dat new file mode 100644 index 00000000..c3832e84 Binary files /dev/null and b/app/src/main/assets/dats/1_2_13-player.dat differ diff --git a/app/src/main/assets/dats/1_2_13.dat b/app/src/main/assets/dats/1_2_13.dat new file mode 100644 index 00000000..fcc54410 Binary files /dev/null and b/app/src/main/assets/dats/1_2_13.dat differ diff --git a/app/src/main/assets/entity_wiki.png b/app/src/main/assets/entity_wiki.png index 5fa336a7..48c4f6f3 100644 Binary files a/app/src/main/assets/entity_wiki.png and b/app/src/main/assets/entity_wiki.png differ diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 00000000..0542d102 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/BackupActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/BackupActivity.java new file mode 100644 index 00000000..b68633f2 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/BackupActivity.java @@ -0,0 +1,209 @@ +package com.mithrilmania.blocktopograph; + +import android.annotation.SuppressLint; +import android.os.AsyncTask; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.mithrilmania.blocktopograph.backup.Backup; +import com.mithrilmania.blocktopograph.backup.WorldBackups; +import com.mithrilmania.blocktopograph.databinding.ActivityBackupBinding; +import com.mithrilmania.blocktopograph.databinding.ItemBackupBinding; +import com.mithrilmania.blocktopograph.util.Consumer; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.util.Date; + +public class BackupActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener { + + private ActivityBackupBinding mBinding; + + private WorldBackups mBackups; + + private MeowAdapter mBackupsListAdapter; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this, R.layout.activity_backup); + World world = (World) (savedInstanceState == null + ? getIntent().getSerializableExtra(World.ARG_WORLD_SERIALIZED) + : savedInstanceState.getSerializable(World.ARG_WORLD_SERIALIZED)); + if (world == null) { + finish(); + return; + } + mBackups = new WorldBackups(world); + mBackups.loadConfig(); + mBinding.setBackups(mBackups); + mBinding.cbAutoBackup.setChecked(mBackups.autoBackup); + mBinding.cbAutoDelete.setChecked(mBackups.autoDelete); + mBinding.cbAutoBackup.setOnCheckedChangeListener(this); + mBinding.cbAutoDelete.setOnCheckedChangeListener(this); + mBinding.list.setLayoutManager(new LinearLayoutManager(this)); + mBackupsListAdapter = new MeowAdapter(this::onClickRestore, this::onClickDelete); + mBinding.list.setAdapter(mBackupsListAdapter); + resetList(); + } + + @SuppressLint("StaticFieldLeak") + public void onClickBackup(View view) { + // The progress won't take long then it won't leak. + String name = mBinding.editName.getText().toString().trim(); + String bakName = name.equals("") ? "Backup" : name; + AlertDialog dia = UiUtil.buildProgressWaitDialog(this, R.string.general_please_wait, null); + dia.show(); + new AsyncTask() { + @Override + protected Boolean doInBackground(WorldBackups... worldBackups) { + return worldBackups[0].createNewBackup(bakName, new Date()); + } + + @Override + protected void onPostExecute(Boolean aBoolean) { + if (aBoolean) + UiUtil.toast(BackupActivity.this, R.string.general_done); + else + UiUtil.toast(BackupActivity.this, R.string.general_failed); + synchronized (dia) { + if (dia.isShowing()) dia.dismiss(); + } + resetList(); + } + }.execute(mBackups); + } + + @SuppressLint("StaticFieldLeak") + private void onClickRestore(@NonNull Backup backup) { + // The progress won't take long then it won't leak. + new AlertDialog.Builder(this).setTitle(R.string.restore_caption) + .setMessage(R.string.restore_warn) + .setPositiveButton(android.R.string.ok, (use, less) -> { + AlertDialog dia = UiUtil.buildProgressWaitDialog(this, R.string.general_please_wait, null); + dia.show(); + new AsyncTask() { + @Override + protected Boolean doInBackground(Backup... backups) { + return mBackups.restoreBackup(backups[0]); + } + + @Override + protected void onPostExecute(Boolean aBoolean) { + if (aBoolean) + UiUtil.toast(BackupActivity.this, R.string.general_done); + else + UiUtil.toast(BackupActivity.this, R.string.general_failed); + synchronized (dia) { + if (dia.isShowing()) dia.dismiss(); + } + } + }.execute(backup); + }).setNegativeButton(android.R.string.cancel, null).create().show(); + } + + private void onClickDelete(@NonNull Backup backup) { + new AlertDialog.Builder(this).setTitle(R.string.backup_delete_caption) + .setMessage(R.string.backup_delete_warn) + .setPositiveButton(android.R.string.ok, (use, less) -> { + mBackups.deleteBackup(backup); + resetList(); + }) + .setNegativeButton(android.R.string.cancel, null).create().show(); + } + + private void resetList() { + mBackups.cleanOldBackups(new Date()); + mBackupsListAdapter.setData(mBackups.getBackups()); + } + + + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + switch (compoundButton.getId()) { + case R.id.cb_auto_backup: + if (b) { + new AlertDialog.Builder(this) + .setMessage(R.string.enable_auto_backup_note) + .setTitle(R.string.enable_auto_backup_title) + .setPositiveButton(android.R.string.ok, (use, less) -> mBackups.setAutoBackup(true, getString(R.string.backup_readme))) + .create().show(); + } else + mBackups.setAutoBackup(false, getString(R.string.backup_readme)); + break; + case R.id.cb_auto_delete: + mBackups.setAutoDelete(b, getString(R.string.backup_readme)); + break; + } + } + + private static class MeowAdapter extends RecyclerView.Adapter { + + @NonNull + private Consumer mRestorer; + + @NonNull + private Consumer mDeleter; + + @Nullable + private Backup[] data; + + MeowAdapter(@NonNull Consumer restorer, + @NonNull Consumer deleter) { + mRestorer = restorer; + mDeleter = deleter; + } + + public void setData(@Nullable Backup[] data) { + this.data = data; + notifyDataSetChanged(); + } + + @NonNull + @Override + public MeowHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new MeowHolder(DataBindingUtil.inflate( + LayoutInflater.from(parent.getContext()), R.layout.item_backup, parent, false + )); + } + + @Override + public void onBindViewHolder(@NonNull MeowHolder holder, int position) { + if (data != null) holder.setData(data[position]); + } + + @Override + public int getItemCount() { + return data == null ? 0 : data.length; + } + + private class MeowHolder extends RecyclerView.ViewHolder { + + @NonNull + private ItemBackupBinding mBinding; + + MeowHolder(@NonNull ItemBackupBinding binding) { + super(binding.getRoot()); + mBinding = binding; + mBinding.buttonRestore.setOnClickListener(v -> mRestorer.accept(mBinding.getBackup())); + mBinding.buttonDelete.setOnClickListener(v -> mDeleter.accept(mBinding.getBackup())); + } + + public void setData(Backup backup) { + mBinding.setBackup(backup); + } + + } + + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/BiomeSelectDialog.java b/app/src/main/java/com/mithrilmania/blocktopograph/BiomeSelectDialog.java new file mode 100644 index 00000000..db7566d5 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/BiomeSelectDialog.java @@ -0,0 +1,75 @@ +package com.mithrilmania.blocktopograph; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; + +import com.mithrilmania.blocktopograph.databinding.DialogPickBiomeBinding; +import com.mithrilmania.blocktopograph.databinding.ItemPickBiomeBinding; +import com.mithrilmania.blocktopograph.map.Biome; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +public final class BiomeSelectDialog extends AppCompatActivity { + + public static final String KEY_BIOME = "biome"; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setResult(RESULT_CANCELED); + + DialogPickBiomeBinding binding = DataBindingUtil.setContentView(this, R.layout.dialog_pick_biome); + binding.list.setLayoutManager(new LinearLayoutManager(this)); + binding.list.setAdapter(new MeowAdapter()); + } + + private class MeowAdapter extends RecyclerView.Adapter { + + @NonNull + @Override + public MeowHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + ItemPickBiomeBinding binding = DataBindingUtil.inflate( + getLayoutInflater(), R.layout.item_pick_biome, parent, false + ); + MeowHolder meowHolder = new MeowHolder(binding.getRoot()); + meowHolder.binding = binding; + binding.biomeView.setOnClickListener(v -> { + Biome biome = meowHolder.binding.getBiome(); + setResult(RESULT_OK, new Intent().putExtra(KEY_BIOME, biome)); + finish(); + }); + return meowHolder; + } + + @Override + public void onBindViewHolder(@NonNull MeowHolder holder, int position) { + Biome biome = Biome.values()[position]; + UiUtil.blendBlockColor(holder.binding.biomeView, biome); + holder.binding.setBiome(biome); + } + + @Override + public int getItemCount() { + return Biome.values().length; + } + + private class MeowHolder extends RecyclerView.ViewHolder { + + private ItemPickBiomeBinding binding; + + MeowHolder(@NonNull View itemView) { + super(itemView); + } + } + + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/CreateWorldActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/CreateWorldActivity.java new file mode 100644 index 00000000..2a8cb728 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/CreateWorldActivity.java @@ -0,0 +1,376 @@ +package com.mithrilmania.blocktopograph; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.AssetManager; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.view.View; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.Fragment; + +import com.litl.leveldb.DB; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.ListingBlock; +import com.mithrilmania.blocktopograph.databinding.ActivityCreateWorldBinding; +import com.mithrilmania.blocktopograph.flat.EditFlatFragment; +import com.mithrilmania.blocktopograph.flat.FlatLayers; +import com.mithrilmania.blocktopograph.flat.Layer; +import com.mithrilmania.blocktopograph.map.Biome; +import com.mithrilmania.blocktopograph.nbt.InventoryHolder; +import com.mithrilmania.blocktopograph.nbt.ItemTag; +import com.mithrilmania.blocktopograph.nbt.Keys; +import com.mithrilmania.blocktopograph.nbt.convert.LevelDataConverter; +import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; +import com.mithrilmania.blocktopograph.nbt.convert.NBTInputStream; +import com.mithrilmania.blocktopograph.nbt.convert.NBTOutputStream; +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.LongTag; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; +import com.mithrilmania.blocktopograph.util.ConvertUtil; +import com.mithrilmania.blocktopograph.util.IoUtil; +import com.mithrilmania.blocktopograph.util.McUtil; +import com.mithrilmania.blocktopograph.util.UiUtil; +import com.tomergoldst.tooltips.ToolTip; +import com.tomergoldst.tooltips.ToolTipsManager; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.lang.ref.WeakReference; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import static android.content.res.AssetManager.ACCESS_STREAMING; + + +public final class CreateWorldActivity extends AppCompatActivity { + + public static final int REQUEST_CODE_PICK_BIOME = 2012; + private ActivityCreateWorldBinding mBinding; + private ToolTipsManager mToolTipsManager; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this, R.layout.activity_create_world); + //mBinding.scroll.post(()->mBinding.scroll.doOverScroll()); + mToolTipsManager = new ToolTipsManager(); + Log.logFirebaseEvent(this, Log.CustomFirebaseEvent.CREATE_WORLD_OPEN); + + setBiomeToView(Biome.JUNGLE); + } + + public void onClickPositiveButton(View view) { + //Toast.makeText(this, "fuck", Toast.LENGTH_SHORT).show(); + new CreateWorldTask(this).execute(); + } + + public void onClickHelpLayers(View view) { + View anchorView = (View) view.getParent(); + if (mToolTipsManager.findAndDismiss(anchorView)) return; + ToolTip.Builder builder = new ToolTip.Builder( + this, anchorView, mBinding.helpFrameLayers, + getString(R.string.edit_flat_help), ToolTip.POSITION_ABOVE) + .setAlign(ToolTip.ALIGN_LEFT); + mToolTipsManager.show(builder.build()); + } + + public void onClickChangeBiome(View view) { + startActivityForResult(new Intent(this, BiomeSelectDialog.class), REQUEST_CODE_PICK_BIOME); + } + + private void setBiomeToView(@NonNull Biome biome) { + UiUtil.blendBlockColor(mBinding.biomeView.root, biome); + mBinding.biomeView.setBiome(biome); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (requestCode == REQUEST_CODE_PICK_BIOME) { + if (resultCode == RESULT_OK && data != null) { + Serializable ser = data.getSerializableExtra(BiomeSelectDialog.KEY_BIOME); + if (ser instanceof Biome) setBiomeToView((Biome) ser); + } + } + super.onActivityResult(requestCode, resultCode, data); + } + + private static class CreateWorldTask extends AsyncTask { + + private final WeakReference thiz; + private boolean canProceed; + private boolean mIsVanillaFlat; + private String mName; + private int mBiome; + private int mVersion; + private List layers; + + private CreateWorldTask(CreateWorldActivity thiz) { + this.thiz = new WeakReference<>(thiz); + } + + @Override + protected void onPreExecute() { + CreateWorldActivity activity = thiz.get(); + if (activity == null) { + canProceed = false; + return; + } + int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (permission != PackageManager.PERMISSION_GRANTED) { + Toast.makeText(activity, R.string.no_read_write_access, Toast.LENGTH_SHORT).show(); + canProceed = false; + return; + } + canProceed = true; + mName = activity.mBinding.worldName.getText().toString(); + mVersion = activity.mBinding.version.getCheckedRadioButtonId(); + Biome biome = activity.mBinding.biomeView.getBiome(); + mBiome = biome == null ? 21 : biome.id; + Fragment fr = activity.getSupportFragmentManager().findFragmentById(R.id.frag_layers); + EditFlatFragment frag = (EditFlatFragment) fr; + assert frag != null; + layers = frag.getResultLayers(); + } + + @Override + @NonNull + protected Boolean doInBackground(Void... voids) { + + // Check existing failure. + if (!canProceed) return false; + + // Make sure activity available. + CreateWorldActivity activity = thiz.get(); + if (activity == null) return false; + + // Make sure worlds dir exists. + File worldsDir = McUtil.getMinecraftWorldsDir(Environment.getExternalStorageDirectory()); + if (!worldsDir.isDirectory()) { + if (!worldsDir.mkdirs()) return false; + } + + // Get name. + String name = mName; + if (name.isEmpty() || name.trim().isEmpty()) { + name = activity.getString(R.string.create_world_default_name); + } + + // Get biome. + // + + // Get version. + String verStr; + if (mVersion == R.id.version_aqua) { + verStr = "1_2_13"; + } else { + verStr = "unknown"; + } + + // Get dir. + String dirName = ConvertUtil.getLegalFileName(name) + "[" + verStr + "]"; + File wDir = new File(worldsDir, dirName); + if (wDir.exists()) { + int cnt = 0; + do { + wDir = new File(worldsDir, dirName + '_' + cnt); + cnt++; + } while (wDir.exists() && cnt < 1000); + } + if (!wDir.mkdir()) return false; + + // Get dat. + AssetManager ass = activity.getAssets(); + CompoundTag rootTag = null; + try { + InputStream is = ass.open("dats/" + verStr + ".dat", ACCESS_STREAMING); + rootTag = LevelDataConverter.read(is); + } catch (Exception e) { + Log.d(this, e); + } + if (rootTag == null) return false; + + // Modify dat. + { + // Name. + Tag tag = rootTag.getChildTagByKey(Keys.LEVEL_NAME); + StringTag stag = (StringTag) tag; + stag.setValue(name); + + // Layers. + tag = rootTag.getChildTagByKey(Keys.FLAT_WORLD_LAYERS); + int lsize = layers.size(); + if (lsize != 4) mIsVanillaFlat = false; + else { + Layer ltest = layers.get(0); + mIsVanillaFlat = ltest.block == BlockTemplates.getOfType("minecraft:tallgrass")[0] + && ltest.amount == 1 + && (ltest = layers.get(1)).block == BlockTemplates.getOfType("minecraft:grass")[0] + && ltest.amount == 1 + && (ltest = layers.get(2)).block == BlockTemplates.getOfType("minecraft:dirt")[0] + && ltest.amount == 29 + && (ltest = layers.get(3)).block == BlockTemplates.getOfType("minecraft:bedrock")[0] + && ltest.amount == 1; + } + Layer[] alayers = new Layer[lsize < 3 ? 3 : lsize]; + for (int i = 0; i < lsize; i++) { + alayers[i] = layers.get(lsize - i - 1); + } + // Actually there have to be at least 3 layers, but we don't need to inform users. + for (int i = lsize; i < 3; i++) { + // Fill with air of no amount. + Layer air = new Layer(); + air.amount = 0; + alayers[i] = air; + } + FlatLayers flatLayers = FlatLayers.createNew(mBiome, alayers); + stag = (StringTag) tag; + stag.setValue(flatLayers.write()); + + // Time. + tag = rootTag.getChildTagByKey(Keys.LAST_PLAYED); + LongTag ltag = (LongTag) tag; + ltag.setValue(System.currentTimeMillis() / 1000); + } + + // Write dat. + try { + LevelDataConverter.write(rootTag, McUtil.getLevelDatFile(wDir)); + } catch (IOException e) { + Log.d(this, e); + return false; + } + + // Write levelname. + if (!IoUtil.writeTextFile(McUtil.getLevelNameFile(wDir), name)) return false; + + // Write ad. + IoUtil.writeTextFile( + new File(wDir, activity.getString(R.string.create_world_extra_file_name)), + activity.getString(R.string.create_world_extra_file_text)); + + // Write player. + try { + // Load template from assets. + NBTInputStream nis = new NBTInputStream( + ass.open("dats/" + verStr + "-player.dat", ACCESS_STREAMING), + false, true); + CompoundTag playerTag = (CompoundTag) nis.readTag(); + + // Modify inventory. + InventoryHolder inv = InventoryHolder.readFromPlayer(playerTag); + assert inv != null; + + // Create a book in the first slot. + InventoryHolder.Item item = inv.getItemOfSlot((short) 0); + assert item != null; + //item.setName("minecraft:written_book"); + item.setId((short) 387); + item.setCount((byte) 1); + item.setDamage((short) 0); + + // Its nbt data. + ItemTag itag = item.getItemTag(); + assert itag != null; + itag.setId(-19260817L); + itag.setGeneration(0); + itag.setAuthor("Blocktopograph"); + itag.setTitle(activity.getString(R.string.create_world_book_title)); + //itag.setXuid("2535445286243008"); + CompoundTag page = itag.getPage(0); + assert page != null; + @SuppressLint("SimpleDateFormat") + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + ItemTag.setPageText(page, activity.getString( + R.string.create_world_book_page_0, dateFormat.format(new Date()))); + ItemTag.setPageUrl(page, "https://play.google.com/store/apps/details?id=rbq2012.blocktopograph"); + { + page = itag.getPage(1); + assert page != null; + StringBuilder pager = new StringBuilder(); + pager.append(activity.getString(R.string.create_world_book_recipe_header)); + int lines = layers.size(); + boolean tooManyLines; + if (lines > 8) { + lines = 7; + tooManyLines = true; + } else { + tooManyLines = false; + if (lines < 5) pager.append('\n'); + } + for (int i = 0; i < lines; i++) { + Layer layer = layers.get(i); + int maxlen = 12 - Integer.toString(layer.amount).length(); + String nam; + if (maxlen <= 0) nam = ""; + else { + String namo = layer.block.getBlock().getName(); + if (namo.length() >= maxlen) nam = namo.substring(0, maxlen); + else nam = namo; + } + pager.append(activity.getString( + R.string.create_world_book_recipe_format, layer.amount, nam)); + } + if (tooManyLines) + pager.append(activity.getString(R.string.create_world_book_recipe_many)); + ItemTag.setPageText(page, pager.toString()); + } + // Write to DB. + DB db = new DB(new File(wDir, "db")); + db.open(); + // Size enough for the 5KB data. + ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); + NBTOutputStream nos = new NBTOutputStream(baos, false, true); + nos.writeTag(playerTag); + nos.close(); + db.put("~local_player".getBytes(NBTConstants.CHARSET), baos.toByteArray()); + db.close(); + } catch (Exception e) { + Log.d(this, e); + return false; + } + + return true; + } + + @Override + protected void onPostExecute(Boolean aBoolean) { + assert aBoolean != null; + Activity activity = thiz.get(); + if (activity == null) return; + Bundle params = new Bundle(); + int type; + if (aBoolean) { + if (mIsVanillaFlat) type = 1; + else type = 3 + layers.size(); + } else type = 0; + params.putInt(Log.ANA_PARAM_CREATE_WORLD_TYPE, type); + Log.logFirebaseEvent(activity, Log.CustomFirebaseEvent.CREATE_WORLD_SAVE, params); + if (aBoolean) { + Toast.makeText(activity, + activity.getString(R.string.general_done), + Toast.LENGTH_SHORT).show(); + activity.finish(); + } else { + Toast.makeText(activity, + activity.getString(R.string.general_failed) + , Toast.LENGTH_SHORT).show(); + } + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/Log.java b/app/src/main/java/com/mithrilmania/blocktopograph/Log.java index 0ef7dd46..d32a3000 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/Log.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/Log.java @@ -1,26 +1,119 @@ package com.mithrilmania.blocktopograph; +import android.content.Context; +import android.os.Bundle; + +import androidx.annotation.NonNull; + +import com.google.firebase.crashlytics.FirebaseCrashlytics; +import com.google.firebase.analytics.FirebaseAnalytics; + +import java.io.PrintWriter; +import java.io.StringWriter; + public class Log { - //TODO This is kind of lazy, but repeating the Log.d(*msg*) everywhere is obnoxious - //TODO log only if debug mode is on? + public static final String ANA_PARAM_CREATE_WORLD_TYPE = "cw_type"; + public static final String ANA_PARAM_MAINACT_MENU_TYPE = "mam_type"; + public static final int ANA_PARAM_MAINACT_MENU_TYPE_OPEN = 123; + public static final int ANA_PARAM_MAINACT_MENU_TYPE_HELP = 130; + public static final int ANA_PARAM_MAINACT_MENU_TYPE_ABOUT = 199; + + private static final String LOG_TAG = "Blocktopo"; + + private static FirebaseAnalytics mFirebaseAnalytics; + +// private static PrintWriter mFileLogger; + + private static boolean mIsFirebaseAnalyticsEnabled = false; + private static boolean mIsCrashlyticsEnabled = false; + + private static String prependClassName(@NonNull Object caller, @NonNull String msg) { + Class clazz = caller instanceof Class ? (Class) caller : caller.getClass(); + return clazz.getSimpleName() + ": " + msg; + } + + public static void enableFirebaseAnalytics(@NonNull Context context) { + getFirebaseAnalytics(context).setAnalyticsCollectionEnabled(true); + mIsFirebaseAnalyticsEnabled = true; + } + + public static void enableCrashlytics() { + if (!BuildConfig.DEBUG) { + FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true); + mIsCrashlyticsEnabled = true; + } + } + + public static void d(@NonNull Object caller, @NonNull String msg) { + android.util.Log.d(LOG_TAG, prependClassName(caller, msg)); + } + + public static void d(@NonNull Object caller, @NonNull Throwable throwable) { + StringWriter sw = new StringWriter(4096); + PrintWriter pw = new PrintWriter(sw); + throwable.printStackTrace(pw); + android.util.Log.e(LOG_TAG, prependClassName(caller, sw.toString())); + pw.close(); + } + + public static void e(@NonNull Object caller, @NonNull String msg) { + d(caller, msg); + if (mIsCrashlyticsEnabled) + FirebaseCrashlytics.getInstance().log(prependClassName(caller, msg)); + } - public static final String LOG_TAG = "Blocktopograph"; + public static void e(@NonNull Object caller, @NonNull Throwable throwable) { + d(caller, throwable); + if (mIsCrashlyticsEnabled) FirebaseCrashlytics.getInstance().recordException(throwable); + } - public static void i(String msg){ - android.util.Log.i(LOG_TAG, msg); + private synchronized static FirebaseAnalytics getFirebaseAnalytics(@NonNull Context context) { + if (mFirebaseAnalytics == null) mFirebaseAnalytics = FirebaseAnalytics.getInstance(context); + return mFirebaseAnalytics; } - public static void d(String msg){ - android.util.Log.d(LOG_TAG, msg); + public static void logFirebaseEvent(@NonNull Context context, @NonNull CustomFirebaseEvent firebaseEvent) { + if (mIsFirebaseAnalyticsEnabled) + getFirebaseAnalytics(context).logEvent(firebaseEvent.eventID, new Bundle()); } - public static void w(String msg){ - android.util.Log.w(LOG_TAG, msg); + public static void logFirebaseEvent(@NonNull Context context, @NonNull CustomFirebaseEvent firebaseEvent, @NonNull Bundle eventContent) { + if (mIsFirebaseAnalyticsEnabled) + getFirebaseAnalytics(context).logEvent(firebaseEvent.eventID, eventContent); } - public static void e(String msg){ - android.util.Log.e(LOG_TAG, msg); + // Firebase events, these are meant to be as anonymous as possible, + // pure counters for usage analytics. + // Do not remove! Removing analytics in a fork skews the results to the original userbase! + // Forks should stay in touch, all new features are welcome. + //Wonder why you put these things in a certain Activity. + //That should be global. + public enum CustomFirebaseEvent { + + //max 32 chars: "0123456789abcdef0123456789abcdef" + MAPFRAGMENT_OPEN("map_fragment_open"), + MAPFRAGMENT_RESUME("map_fragment_resume"), + MAPFRAGMENT_RESET("map_fragment_reset"), + NBT_EDITOR_OPEN("nbt_editor_open"), + NBT_EDITOR_SAVE("nbt_editor_save"), + WORLD_OPEN("world_open"), + WORLD_RESUME("world_resume"), + GPS_LOCATE("gps_player"), + MAINACT_MENU_OPEN("mainact_menu"), + CREATE_WORLD_OPEN("create_world_open"), + CREATE_WORLD_SAVE("create_world_save"), + SELECTION("selection_begin"), + SNR_OPEN("snr_open"), + SNR_EXEC("snr_exec"), + DCHUNK("dchunk_open"), + CH_BIOME("ch_biome_open"); + + public final String eventID; + + CustomFirebaseEvent(String eventID) { + this.eventID = eventID; + } } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/MenuHelper.java b/app/src/main/java/com/mithrilmania/blocktopograph/MenuHelper.java deleted file mode 100644 index 8880da71..00000000 --- a/app/src/main/java/com/mithrilmania/blocktopograph/MenuHelper.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.mithrilmania.blocktopograph; - -import android.app.AlertDialog; -import android.content.Context; -import android.text.Html; -import android.text.method.LinkMovementMethod; -import android.view.MenuItem; -import android.widget.TextView; - -public class MenuHelper { - - public interface MenuContext { - - Context getContext(); - - boolean propagateOnOptionsItemSelected(MenuItem menuItem); - - } - - public static boolean onOptionsItemSelected(MenuContext menuContext, MenuItem item) { - - Context ctx = menuContext.getContext(); - - //some text pop-up dialogs, some with simple HTML tags. - switch (item.getItemId()) { - case R.id.action_about: { - - AlertDialog.Builder builder = new AlertDialog.Builder(ctx); - TextView msg = new TextView(ctx); - float dpi = ctx.getResources().getDisplayMetrics().density; - msg.setPadding((int)(19*dpi), (int)(5*dpi), (int)(14*dpi), (int)(5*dpi)); - msg.setMaxLines(20); - msg.setMovementMethod(LinkMovementMethod.getInstance()); - msg.setText(R.string.app_about); - builder.setView(msg) - .setTitle(R.string.action_about) - .setCancelable(true) - .setNeutralButton(android.R.string.ok, null) - .show(); - - return true; - } - case R.id.action_help: { - AlertDialog.Builder builder = new AlertDialog.Builder(ctx); - TextView msg = new TextView(ctx); - float dpi = ctx.getResources().getDisplayMetrics().density; - msg.setPadding((int)(19*dpi), (int)(5*dpi), (int)(14*dpi), (int)(5*dpi)); - msg.setMaxLines(20); - msg.setMovementMethod(LinkMovementMethod.getInstance()); - msg.setText(R.string.app_help); - builder.setView(msg) - .setTitle(R.string.action_help) - .setCancelable(true) - .setNeutralButton(android.R.string.ok, null) - .show(); - - return true; - } - case R.id.action_changelog: { - AlertDialog.Builder builder = new AlertDialog.Builder(ctx); - TextView msg = new TextView(ctx); - float dpi = ctx.getResources().getDisplayMetrics().density; - msg.setPadding((int)(19*dpi), (int)(5*dpi), (int)(14*dpi), (int)(5*dpi)); - msg.setMaxLines(20); - msg.setMovementMethod(LinkMovementMethod.getInstance()); - String content = String.format(ctx.getResources().getString(R.string.app_changelog), BuildConfig.VERSION_NAME); - //noinspection deprecation - msg.setText(Html.fromHtml(content)); - builder.setView(msg) - .setTitle(R.string.action_changelog) - .setCancelable(true) - .setNeutralButton(android.R.string.ok, null) - .show(); - - return true; - } - default: { - return menuContext.propagateOnOptionsItemSelected(item); - } - } - } - -} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/SplashScreen.java b/app/src/main/java/com/mithrilmania/blocktopograph/SplashScreen.java index 4f5a2028..b2a9fa00 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/SplashScreen.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/SplashScreen.java @@ -1,7 +1,6 @@ package com.mithrilmania.blocktopograph; -import android.app.Activity; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -13,7 +12,9 @@ import java.io.IOException; import java.io.InputStream; -public class SplashScreen extends Activity { +import androidx.appcompat.app.AppCompatActivity; + +public class SplashScreen extends AppCompatActivity { // Splash screen timer, in milliseconds private static final int SPLASH_TIME_OUT = 1000; @@ -28,28 +29,27 @@ protected void onCreate(Bundle savedInstanceState) { //3. Keep the splash-screen open till the SPLASH_TIME_OUT (started at #1) is over //4. Done! Some quick brand-awareness. + // Hey proto where did you copy these shit from... + // Why did you went through 3rd party outdated Android tutorial + // instead the official one......... + //Comment: yes, splash-screens are against Material-design android guide-lines, // but brand-awareness is important. And it is a very quick splash (just 1 sec!) - ImageView brandLogoView = (ImageView) this.findViewById(R.id.brandLogo); - - new Handler().postDelayed(new Runnable() { + ImageView brandLogoView = this.findViewById(R.id.brandLogo); - /* - * Showing splash screen with a timer. This will be useful when you - * want to show case your app logo / company - */ + /* + * Showing splash screen with a timer. This will be useful when you + * want to show case your app logo / company + */ + new Handler().postDelayed(() -> { + // This method will be executed once the timer is over + // Start your app main activity + Intent i = new Intent(SplashScreen.this, WorldItemListActivity.class); + SplashScreen.this.startActivity(i); - @Override - public void run() { - // This method will be executed once the timer is over - // Start your app main activity - Intent i = new Intent(SplashScreen.this, WorldItemListActivity.class); - SplashScreen.this.startActivity(i); + //user can not go back to splashscreen + SplashScreen.this.finish(); - //user can not go back to splashscreen - SplashScreen.this.finish(); - - } }, SPLASH_TIME_OUT); @@ -61,8 +61,7 @@ public void run() { Drawable d = Drawable.createFromStream(ims, null); // set image to ImageView brandLogoView.setImageDrawable(d); - } - catch(IOException ex) { + } catch (IOException ex) { //fail, but xml has app icon as backup logo (lower resolution, from #1) } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/UnsatisfiedLinkErrorActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/UnsatisfiedLinkErrorActivity.java new file mode 100644 index 00000000..7ce90577 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/UnsatisfiedLinkErrorActivity.java @@ -0,0 +1,14 @@ +package com.mithrilmania.blocktopograph; + +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +public class UnsatisfiedLinkErrorActivity extends AppCompatActivity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_unsatisfied_link_error); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/World.java b/app/src/main/java/com/mithrilmania/blocktopograph/World.java index da95f088..77901b44 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/World.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/World.java @@ -1,168 +1,314 @@ package com.mithrilmania.blocktopograph; +import android.content.Context; +import android.os.Bundle; +import android.util.SparseIntArray; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.litl.leveldb.Iterator; +import com.mithrilmania.blocktopograph.chunk.Chunk; +import com.mithrilmania.blocktopograph.map.Dimension; import com.mithrilmania.blocktopograph.map.MarkerManager; +import com.mithrilmania.blocktopograph.nbt.convert.DataConverter; import com.mithrilmania.blocktopograph.nbt.convert.LevelDataConverter; import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.IntTag; +import com.mithrilmania.blocktopograph.nbt.tags.ListTag; import com.mithrilmania.blocktopograph.nbt.tags.LongTag; -import com.mithrilmania.blocktopograph.util.io.TextFile; -import com.litl.leveldb.Iterator; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; +import com.mithrilmania.blocktopograph.util.IoUtil; +import com.mithrilmania.blocktopograph.util.math.DimensionVector3; import java.io.File; import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; public class World implements Serializable { - private static final long serialVersionUID = 792709417041090031L; - - public String getWorldDisplayName() { - if(worldName == null) return null; - //return worldname, without special color codes - // (character prefixed by the section-sign character) - // Short quick regex, shouldn't affect performance too much - return worldName.replaceAll("\u00A7.", ""); - } - - public enum SpecialDBEntryType { - - //Who came up with the formatting for these NBT keys is CRAZY - // (PascalCase, camelCase, snake_case, lowercase, m-prefix(Android), tilde-prefix; it's all there!) - BIOME_DATA("BiomeData"), - OVERWORLD("Overworld"), - M_VILLAGES("mVillages"), - PORTALS("portals"), - LOCAL_PLAYER("~local_player"), - AUTONOMOUS_ENTITIES("AutonomousEntities"), - DIMENSION_0("dimension0"), - DIMENSION_1("dimension1"), - DIMENSION_2("dimension2"); - - public final String keyName; - public final byte[] keyBytes; - - SpecialDBEntryType(String keyName){ - this.keyName = keyName; - this.keyBytes = keyName.getBytes(NBTConstants.CHARSET); - } - } - // The World (just a WorldData handle) is serializable, this is the tag used in the android workflow public static final String ARG_WORLD_SERIALIZED = "world_ser"; + private static final long serialVersionUID = 792709417041090031L; - - public final String worldName; - + public static final String KEY_HAS_ERROR = "hasError"; + public static final String KEY_FLAT_WORLD_LAYERS = "FlatWorldLayers"; + public static final String KEY_GAME_TYPE = "GameType"; + public static final String KEY_GENERATOR = "Generator"; + public static final String KEY_INVENTORY_VERSION = "InventoryVersion"; + public static final String KEY_MINIMUM_VERSION = "MinimumCompatibleClientVersion"; + public static final String KEY_MINIMUM_VERSION_SHORT = "MinClientVersion"; + public static final String KEY_STORAGE_VERSION = "StorageVersion"; + public static final String KEY_LAST_VERSION = "lastOpenedWithVersion"; + public static final String KEY_LAST_VERSION_SHORT = "lastWithVersion"; + public static final String KEY_SHOW_COORDINATES = "showcoordinates"; + + public String mark; + private final String worldName; public final File worldFolder; - - private transient WorldData worldData; - - public final File levelFile; + private CompoundTag level; + private transient WorldData worldData; + private transient MarkerManager markersManager; - public CompoundTag level; - - public static class WorldLoadException extends Exception { - private static final long serialVersionUID = 1812348294537392782L; - - public WorldLoadException(String msg){ super(msg); } - } + private boolean mHaveBackgroundJob; + public World(File worldFolder, String mark, @NonNull Context context) throws WorldLoadException { - public World(File worldFolder) throws WorldLoadException { + if (!worldFolder.exists()) + throw new WorldLoadException("Error: '" + worldFolder.getPath() + "' does not exist!"); - if(!worldFolder.exists()) throw new WorldLoadException("Error: '"+worldFolder.getPath()+"' does not exist!"); + this.mark = mark; this.worldFolder = worldFolder; // check for a custom world name File levelNameTxt = new File(this.worldFolder, "levelname.txt"); - if(levelNameTxt.exists()) worldName = TextFile.readTextFileFirstLine(levelNameTxt);// new way of naming worlds - else worldName = this.worldFolder.getName();// legacy way of naming worlds + this.levelFile = new File(this.worldFolder, "level.dat"); + if (levelNameTxt.exists()) + worldName = IoUtil.readTextFileFirstLine(levelNameTxt);// new way of naming worlds + else if (levelFile.exists()) + worldName = this.worldFolder.getName();// legacy way of naming worlds + else worldName = context.getString(R.string.world_name_broken); - this.levelFile = new File(this.worldFolder, "level.dat"); - if(!levelFile.exists()) throw new WorldLoadException("Error: Level-file: '"+levelFile.getPath()+"' does not exist!"); + } - try { - this.level = LevelDataConverter.read(levelFile); - } catch (IOException e) { - e.printStackTrace(); - throw new WorldLoadException("Error: failed to read level: '"+levelFile.getPath()+"' !"); - } + public CompoundTag getLevel() { + if (level == null) + try { + this.level = LevelDataConverter.read(levelFile); + } catch (IOException e) { + e.printStackTrace(); + } + return level; + } + public String getWorldDisplayName() { + if (worldName == null) return null; + //return worldname, without special color codes + // (character prefixed by the section-sign character) + return worldName.replaceAll("\u00A7.", ""); } - public long getWorldSeed(){ - if(this.level == null) return 0; + public long getWorldSeed() { + if (this.level == null) return 0; LongTag seed = (LongTag) this.level.getChildTagByKey("RandomSeed"); return seed == null ? 0 : seed.getValue(); } + @Nullable + public Bundle getMapVersionData() { + try { + Bundle bundle = new Bundle(); + { + Tag tag = level.getChildTagByKey(KEY_STORAGE_VERSION); + int ver; + if (!(tag instanceof IntTag)) ver = -1; + else { + Integer intInt = ((IntTag) tag).getValue(); + ver = intInt == null ? -1 : intInt; + } + bundle.putInt(KEY_STORAGE_VERSION, ver); + } + { + Tag tag = level.getChildTagByKey(KEY_INVENTORY_VERSION); + String ver; + if (!(tag instanceof StringTag)) ver = null; + else ver = ((StringTag) tag).getValue(); + bundle.putString(KEY_INVENTORY_VERSION, ver); + } + { + Tag tag = level.getChildTagByKey(KEY_LAST_VERSION); + ArrayList ver; + if (!(tag instanceof ListTag)) ver = null; + else ver = ((ListTag) tag).getValue(); + StringBuilder sb = new StringBuilder(); + if (ver != null) for (Tag t : ver) { + int iver; + if (!(t instanceof IntTag)) iver = -1; + else iver = ((IntTag) t).getValue(); + sb.append(iver).append('.'); + } + bundle.putString(KEY_LAST_VERSION_SHORT, sb.toString()); + } + { + Tag tag = level.getChildTagByKey(KEY_MINIMUM_VERSION); + ArrayList ver; + if (!(tag instanceof ListTag)) ver = null; + else ver = ((ListTag) tag).getValue(); + StringBuilder sb = new StringBuilder(); + if (ver != null) for (Tag t : ver) { + int iver; + if (!(t instanceof IntTag)) iver = -1; + else iver = ((IntTag) t).getValue(); + sb.append(iver).append('.'); + } + bundle.putString(KEY_MINIMUM_VERSION_SHORT, sb.toString()); + } + Iterator iterator = null; + try { + SparseIntArray versions = new SparseIntArray(); + //SparseIntArray dimensions = new SparseIntArray(); + iterator = getWorldData().db.iterator(); + int count = 0; + for (iterator.seekToFirst(); iterator.isValid() && count < 800; iterator.next(), count++) { + byte[] key = iterator.getKey(); + if ((key.length == 9 && key[8] == 0x76) || (key.length == 13 && key[12] == 0x76)) { + //if (key.length == 9) dimensions.put(0, dimensions.get(0) + 1); + //else { + // int dimension = (key[8] & 0xff) | ((key[9] & 0xff) << 8) | ((key[10] & 0xff) << 16) | (key[11] << 24); + // dimensions.put(dimension, dimensions.get(dimension) + 1); + //} + byte[] val = iterator.getValue(); + versions.put(val[0], versions.get(val[0]) + 1); + } + } + iterator.close(); + StringBuilder sb = new StringBuilder(); + for (int i = 0, lim = Math.min(versions.size(), 8); i < lim; i++) { + sb.append(versions.keyAt(i)).append(':').append(versions.valueAt(i)).append(','); + } + bundle.putString("chunks", sb.toString()); + } catch (Exception e) { + e.printStackTrace(); + if (iterator != null) { + iterator.close(); + } + } + return bundle; + } catch (Exception e) { + Log.e(this, e); + return null; + } + } + public void writeLevel(CompoundTag level) throws IOException { LevelDataConverter.write(level, this.levelFile); this.level = level; } - private MarkerManager markersManager; - - public MarkerManager getMarkerManager() { - if(markersManager == null) - markersManager = new MarkerManager(new File(this.worldFolder, "markers.txt")); + @NonNull + public DimensionVector3 getMultiPlayerPos(String dbKey) throws Exception { + try { + WorldData wData = getWorldData(); + wData.openDB(); + byte[] data = wData.db.get(dbKey.getBytes(NBTConstants.CHARSET)); + if (data == null) throw new Exception("no data!"); + final CompoundTag player = (CompoundTag) DataConverter.read(data).get(0); + + ListTag posVec = (ListTag) player.getChildTagByKey("Pos"); + if (posVec == null || posVec.getValue() == null) + throw new Exception("No \"Pos\" specified"); + if (posVec.getValue().size() != 3) + throw new Exception("\"Pos\" value is invalid. value: " + posVec.getValue().toString()); + + IntTag dimensionId = (IntTag) player.getChildTagByKey("DimensionId"); + if (dimensionId == null || dimensionId.getValue() == null) + throw new Exception("No \"DimensionId\" specified"); + Dimension dimension = Dimension.getDimension(dimensionId.getValue()); + if (dimension == null) dimension = Dimension.OVERWORLD; + + return new DimensionVector3<>( + (float) posVec.getValue().get(0).getValue(), + (float) posVec.getValue().get(1).getValue(), + (float) posVec.getValue().get(2).getValue(), + dimension); - return markersManager; + } catch (Exception e) { + Log.d(this, e); + Exception e2 = new Exception("Could not find " + dbKey); + e2.setStackTrace(e.getStackTrace()); + throw e2; + } } - /** - * @return worldFolder name, also unique save-file ID - */ - public String getID(){ - return this.worldFolder.getName(); - } + @Nullable + public DimensionVector3 getPlayerPos() { + try { + WorldData wData = getWorldData(); + wData.openDB(); + byte[] data = wData.db.get(World.SpecialDBEntryType.LOCAL_PLAYER.keyBytes); + final CompoundTag player = data != null + ? (CompoundTag) DataConverter.read(data).get(0) + : (CompoundTag) getLevel().getChildTagByKey("Player"); - public WorldData getWorldData(){ - if(this.worldData == null) this.worldData = new WorldData(this); - return this.worldData; - } + if (player == null) { + Log.d(this, "No local player. A server world?"); + return null; + } - /* - public byte[] loadChunkData(int chunkX, int chunkZ, ChunkTag dataType, Dimension dimension) throws WorldData.WorldDBLoadException, WorldData.WorldDBException { - return getWorldData().getChunkData(chunkX, chunkZ, dataType, dimension); - } + ListTag posVec = (ListTag) player.getChildTagByKey("Pos"); + IntTag dimensionId = (IntTag) player.getChildTagByKey("DimensionId"); + Dimension dimension = Dimension.getDimension(dimensionId.getValue()); + if (dimension == null) dimension = Dimension.OVERWORLD; - public void saveChunkData(int chunkX, int chunkZ, ChunkData chunkData) throws IOException, WorldData.WorldDBException { - byte[] bData = chunkData.toByteArray(); - if (bData != null) getWorldData().writeChunkData(chunkX, chunkZ, chunkData.dataType, bData, chunkData.dimension); - else getWorldData().removeChunkData(chunkX, chunkZ, chunkData.dataType, chunkData.dimension); + return new DimensionVector3<>( + (float) posVec.getValue().get(0).getValue(), + (float) posVec.getValue().get(1).getValue(), + (float) posVec.getValue().get(2).getValue(), + dimension); + } catch (Exception e) { + Log.d(this, e); + return null; + } } + public DimensionVector3 getSpawnPos() throws Exception { + try { + CompoundTag level = getLevel(); + int spawnX = ((IntTag) level.getChildTagByKey("SpawnX")).getValue(); + int spawnY = ((IntTag) level.getChildTagByKey("SpawnY")).getValue(); + int spawnZ = ((IntTag) level.getChildTagByKey("SpawnZ")).getValue(); + if (spawnY >= 256) try { + Chunk chunk = getWorldData().getChunk(spawnX >> 4, spawnZ >> 4, Dimension.OVERWORLD); + if (!chunk.isError()) + spawnY = chunk.getHeightMapValue(spawnX % 16, spawnZ % 16) + 1; + } catch (Exception ignored) { + } + return new DimensionVector3<>(spawnX, spawnY, spawnZ, Dimension.OVERWORLD); + } catch (Exception e) { + Log.d(this, e); + throw new Exception("Could not find spawn"); + } + } - //returns true if creating and saving was successful - public ChunkData createEmptyChunkData(int chunkX, int chunkZ, ChunkTag dataType, Dimension dimension){ + public MarkerManager getMarkerManager() { + if (markersManager == null) + markersManager = new MarkerManager(new File(this.worldFolder, "markers.txt")); - ChunkData data = dataType.newInstance(dimension); - if(data == null) return null; + return markersManager; + } - data.createEmpty(); + /** + * @return worldFolder name, also unique save-file ID + */ + public String getID() { + return this.worldFolder.getName(); + } - try { - this.saveChunkData(chunkX, chunkZ, data); - return data; - } catch (Exception e) { - e.printStackTrace(); - return null; + @NonNull + public WorldData getWorldData() { + if (this.worldData == null) { + this.worldData = new WorldData(this); } + return this.worldData; } - */ public void closeDown() throws WorldData.WorldDBException { - if(this.worldData != null) this.worldData.closeDB(); + if (this.worldData != null) this.worldData.closeDB(); } public void pause() throws WorldData.WorldDBException { - closeDown(); + if (mHaveBackgroundJob) + Log.d(this, "User is doing background job with the app really in background!"); + else + closeDown(); } public void resume() throws WorldData.WorldDBException { @@ -174,7 +320,7 @@ public void resume() throws WorldData.WorldDBException { } //function meant for debugging, not used in production - public void logDBKeys(){ + public void logDBKeys() { try { this.getWorldData(); @@ -182,10 +328,11 @@ public void logDBKeys(){ Iterator it = worldData.db.iterator(); - for(it.seekToFirst(); it.isValid(); it.next()){ + for (it.seekToFirst(); it.isValid(); it.next()) { byte[] key = it.getKey(); byte[] value = it.getValue(); - /*if(key.length == 9 && key[8] == RegionDataType.TERRAIN.dataID) */ Log.d("key: " + new String(key) + " key in Hex: " + WorldData.bytesToHex(key, 0, key.length) + " size: "+value.length); + /*if(key.length == 9 && key[8] == RegionDataType.TERRAIN.dataID) */ + Log.d(this, "key: " + new String(key) + " key in Hex: " + WorldData.bytesToHex(key, 0, key.length) + " size: " + value.length); } @@ -195,4 +342,39 @@ public void logDBKeys(){ e.printStackTrace(); } } + + public void setHaveBackgroundJob(boolean haveBackgroundJob) { + mHaveBackgroundJob = haveBackgroundJob; + } + + public enum SpecialDBEntryType { + + //Who came up with the formatting for these NBT keys is CRAZY + // (PascalCase, camelCase, snake_case, lowercase, m-prefix(Android), tilde-prefix; it's all there!) + BIOME_DATA("BiomeData"), + OVERWORLD("Overworld"), + M_VILLAGES("mVillages"), + PORTALS("portals"), + LOCAL_PLAYER("~local_player"), + AUTONOMOUS_ENTITIES("AutonomousEntities"), + DIMENSION_0("dimension0"), + DIMENSION_1("dimension1"), + DIMENSION_2("dimension2"); + + public final String keyName; + public final byte[] keyBytes; + + SpecialDBEntryType(String keyName) { + this.keyName = keyName; + this.keyBytes = keyName.getBytes(NBTConstants.CHARSET); + } + } + + public static class WorldLoadException extends Exception { + private static final long serialVersionUID = 1812348294537392782L; + + public WorldLoadException(String msg) { + super(msg); + } + } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivity.java index e7b38460..97333fa7 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivity.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivity.java @@ -1,187 +1,158 @@ package com.mithrilmania.blocktopograph; import android.app.AlertDialog; -import android.app.FragmentManager; -import android.app.FragmentTransaction; -import android.content.Context; import android.content.DialogInterface; import android.os.Build; import android.os.Bundle; -import android.support.design.widget.Snackbar; -import android.support.v7.app.ActionBar; import android.text.Editable; -import android.view.View; -import android.support.design.widget.NavigationView; - -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; - -import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; - -import com.google.firebase.analytics.FirebaseAnalytics; -import com.mithrilmania.blocktopograph.map.Dimension; -import com.mithrilmania.blocktopograph.map.marker.AbstractMarker; -import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.view.GravityCompat; +import androidx.databinding.DataBindingUtil; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import com.google.android.material.navigation.NavigationView; +import com.google.android.material.snackbar.Snackbar; import com.mithrilmania.blocktopograph.chunk.NBTChunkData; +import com.mithrilmania.blocktopograph.databinding.ActivityWorldBinding; +import com.mithrilmania.blocktopograph.map.Dimension; import com.mithrilmania.blocktopograph.map.MapFragment; +import com.mithrilmania.blocktopograph.map.TileEntity; +import com.mithrilmania.blocktopograph.map.marker.AbstractMarker; import com.mithrilmania.blocktopograph.map.renderer.MapType; import com.mithrilmania.blocktopograph.nbt.EditableNBT; import com.mithrilmania.blocktopograph.nbt.EditorFragment; import com.mithrilmania.blocktopograph.nbt.convert.DataConverter; +import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; import com.mithrilmania.blocktopograph.nbt.tags.Tag; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + public class WorldActivity extends AppCompatActivity - implements NavigationView.OnNavigationItemSelectedListener, WorldActivityInterface, MenuHelper.MenuContext { + implements NavigationView.OnNavigationItemSelectedListener, WorldActivityInterface { + public static final String PREF_KEY_SHOW_MARKERS = "showMarkers"; private World world; + private ActivityWorldBinding mBinding; private MapFragment mapFragment; - private FirebaseAnalytics mFirebaseAnalytics; - - synchronized public FirebaseAnalytics getFirebaseAnalytics() { - if (mFirebaseAnalytics == null) { - mFirebaseAnalytics = FirebaseAnalytics.getInstance(this); - - //don't measure the test devices in analytics - mFirebaseAnalytics.setAnalyticsCollectionEnabled(!BuildConfig.DEBUG); - } - return mFirebaseAnalytics; - } - - // Firebase events, these are meant to be as anonymous as possible, - // pure counters for usage analytics. - // Do not remove! Removing analytics in a fork skews the results to the original userbase! - // Forks should stay in touch, all new features are welcome. - public enum CustomFirebaseEvent { - - //max 32 chars: "0123456789abcdef0123456789abcdef" - MAPFRAGMENT_OPEN( "map_fragment_open"), - MAPFRAGMENT_RESUME( "map_fragment_resume"), - MAPFRAGMENT_RESET( "map_fragment_reset"), - NBT_EDITOR_OPEN( "nbt_editor_open"), - NBT_EDITOR_SAVE( "nbt_editor_save"), - WORLD_OPEN( "world_open"), - WORLD_RESUME( "world_resume"), - GPS_PLAYER( "gps_player"), - GPS_MULTIPLAYER( "gps_multiplayer"), - GPS_SPAWN( "gps_spawn"), - GPS_MARKER( "gps_marker"), - GPS_COORD( "gps_coord"); - - public final String eventID; - - CustomFirebaseEvent(String eventID){ - this.eventID = eventID; - } + @Override + public void showActionBar() { + ActionBar bar = getSupportActionBar(); + if (bar != null) bar.show(); } @Override - public void logFirebaseEvent(CustomFirebaseEvent firebaseEvent){ - getFirebaseAnalytics().logEvent(firebaseEvent.eventID, new Bundle()); + public void hideActionBar() { + ActionBar bar = getSupportActionBar(); + if (bar != null) bar.hide(); } @Override - public void logFirebaseEvent(CustomFirebaseEvent firebaseEvent, Bundle eventContent){ - getFirebaseAnalytics().logEvent(firebaseEvent.eventID, eventContent); + public void openDrawer() { + mBinding.drawerLayout.openDrawer(mBinding.navView, true); } @Override - public void showActionBar() { - ActionBar bar = getSupportActionBar(); - if(bar != null) bar.show(); + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + getWindow().getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + } + // immersive fullscreen for Android Kitkat and higher +// if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { +// ActionBar bar = getSupportActionBar(); +// if (bar != null) bar.hide(); +// this.getWindow().getDecorView().setSystemUiVisibility( +// View.SYSTEM_UI_FLAG_LAYOUT_STABLE +// | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION +// | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN +// | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION +// | View.SYSTEM_UI_FLAG_FULLSCREEN +// | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); +// } } @Override - public void hideActionBar() { - ActionBar bar = getSupportActionBar(); - if(bar != null) bar.hide(); + protected void onRestart() { + super.onRestart(); } @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - // immersive fullscreen for Android Kitkat and higher - if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - ActionBar bar = getSupportActionBar(); - if(bar != null) bar.hide(); - this.getWindow().getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - } + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable(World.ARG_WORLD_SERIALIZED, world); } @Override protected void onCreate(Bundle savedInstanceState) { - Log.d("World activity creating..."); - super.onCreate(savedInstanceState); - - /* Retrieve world from previous state or intent */ + Log.d(this, "World activity creating..."); this.world = (World) (savedInstanceState == null ? getIntent().getSerializableExtra(World.ARG_WORLD_SERIALIZED) : savedInstanceState.getSerializable(World.ARG_WORLD_SERIALIZED)); - if(world == null){ + if (world == null) { + Toast.makeText(this, "cannot open: world == null", Toast.LENGTH_SHORT).show(); //WTF, try going back to the previous screen by finishing this hopeless activity... finish(); + //Finish does not guarantee codes below won't be executed! + //Shit + return; } + showMarkers = getPreferences(MODE_PRIVATE).getBoolean(PREF_KEY_SHOW_MARKERS, true); /* Layout */ - setContentView(R.layout.activity_world); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - assert toolbar != null; - setSupportActionBar(toolbar); + mBinding = DataBindingUtil.setContentView(this, R.layout.activity_world); + //Toolbar toolbar = mBinding.bar.toolbar; + //assert toolbar != null; + //setSupportActionBar(toolbar); - NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); + NavigationView navigationView = mBinding.navView; assert navigationView != null; navigationView.setNavigationItemSelectedListener(this); // Main drawer, quick access to different menus, tools and map-types. - DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); - ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( - this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); - assert drawer != null; - drawer.setDrawerListener(toggle); - toggle.syncState(); - - +// DrawerLayout drawer = mBinding.drawerLayout; +// ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( +// this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); +// assert drawer != null; +// drawer.addDrawerListener(toggle); +// toggle.syncState(); View headerView = navigationView.getHeaderView(0); assert headerView != null; // Title = world-name - TextView title = (TextView) headerView.findViewById(R.id.world_drawer_title); + TextView title = headerView.findViewById(R.id.world_drawer_title); assert title != null; title.setText(this.world.getWorldDisplayName()); // Subtitle = world-seed (Tap worldseed to choose to copy it) - TextView subtitle = (TextView) headerView.findViewById(R.id.world_drawer_subtitle); + TextView subtitle = headerView.findViewById(R.id.world_drawer_subtitle); assert subtitle != null; /* @@ -199,51 +170,66 @@ Send anonymous world data to the Firebase (Google analytics for Android) server. TODO BigQuery is not configured yet, @mithrilmania (author of Blocktopograph) is working on it! + Ahhh good idea anyway... Then why didn't you continue it. + *link to results will be included here for reference when @mithrilmania is done* */ String worldSeed = String.valueOf(this.world.getWorldSeed()); subtitle.setText(worldSeed); - Bundle bundle = new Bundle(); - bundle.putString("seed", worldSeed); - bundle.putString("name", this.world.getWorldDisplayName()); - - - - // anonymous global counter of opened worlds - logFirebaseEvent(CustomFirebaseEvent.WORLD_OPEN, bundle); - - - // Open the world-map as default content openWorldMap(); - - try { - //try to load world-data (Opens chunk-database for later usage) - this.world.getWorldData().load(); - } catch (WorldData.WorldDataLoadException e) { - finish(); + world.getWorldData().load(); + world.getWorldData().openDB(); + } catch (Exception e) { e.printStackTrace(); + finish(); } +// +// new AsyncTask() { +// @Override +// protected Void doInBackground(Void... voids) { +// +// try { +// //try to load world-data (Opens chunk-database for later usage) +// world.getWorldData().openDB(); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// return null; +// } +// }.execute(); +// finish(); +// if(1==1)return; + + + Bundle bundle = new Bundle(); + bundle.putString("seed", worldSeed); + bundle.putString("name", this.world.getWorldDisplayName()); + Bundle mapVersionData = world.getMapVersionData(); + if (mapVersionData != null) bundle.putAll(mapVersionData); + + // anonymous global counter of opened worlds + Log.logFirebaseEvent(this, Log.CustomFirebaseEvent.WORLD_OPEN, bundle); - Log.d("World activity created"); + Log.d(this, "World activity created"); } @Override - public void onStart(){ - Log.d("World activity starting..."); + public void onStart() { + Log.d(this, "World activity starting..."); super.onStart(); - Log.d("World activity started"); + Log.d(this, "World activity started"); } @Override - public void onResume(){ - Log.d("World activity resuming..."); + public void onResume() { + Log.d(this, "World activity resuming..."); super.onResume(); - +// // anonymous global counter of resumed world-activities - logFirebaseEvent(CustomFirebaseEvent.WORLD_RESUME); + Log.logFirebaseEvent(this, Log.CustomFirebaseEvent.WORLD_RESUME); try { this.world.resume(); @@ -251,12 +237,12 @@ public void onResume(){ this.onFatalDBError(e); } - Log.d("World activity resumed"); + Log.d(this, "World activity resumed"); } @Override - public void onPause(){ - Log.d("World activity pausing..."); + public void onPause() { + Log.d(this, "World activity pausing..."); super.onPause(); try { @@ -265,33 +251,33 @@ public void onPause(){ e.printStackTrace(); } - Log.d("World activity paused"); + Log.d(this, "World activity paused"); } @Override - public void onStop(){ - Log.d("World activity stopping..."); + public void onStop() { + Log.d(this, "World activity stopping..."); super.onStop(); - Log.d("World activity stopped"); + Log.d(this, "World activity stopped"); } @Override - public void onDestroy(){ - Log.d("World activity destroying..."); + public void onDestroy() { + Log.d(this, "World activity destroying..."); super.onDestroy(); - Log.d("World activity destroyed..."); + Log.d(this, "World activity destroyed..."); } @Override public void onBackPressed() { - DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + DrawerLayout drawer = mBinding.drawerLayout; assert drawer != null; if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); return; } - final FragmentManager manager = getFragmentManager(); + final FragmentManager manager = getSupportFragmentManager(); int count = manager.getBackStackEntryCount(); // No opened fragments, so it is using the default fragment @@ -299,89 +285,63 @@ public void onBackPressed() { if (count == 0) { new AlertDialog.Builder(this) - .setMessage(R.string.ask_close_world) - .setCancelable(false) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { + .setMessage(R.string.ask_close_world) + .setCancelable(false) + .setPositiveButton(android.R.string.yes, (dialog, id) -> { + try { + world.closeDown(); + } catch (WorldData.WorldDBException e) { + e.printStackTrace(); + } WorldActivity.this.finish(); - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); + }) + .setNegativeButton(android.R.string.no, null) + .show(); - } else if(confirmContentClose != null){ + } else if (confirmContentClose != null) { //An important fragment is opened, // something that couldn't be reopened in its current state easily, // ask the user if he/she intended to close it. new AlertDialog.Builder(this) - .setMessage(confirmContentClose) - .setCancelable(false) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { + .setMessage(confirmContentClose) + .setCancelable(false) + .setPositiveButton(android.R.string.yes, (dialog, id) -> { manager.popBackStack(); confirmContentClose = null; - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); + }) + .setNegativeButton(android.R.string.no, null) + .show(); } else { //fragment is open, but it may be closed without warning manager.popBackStack(); } } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.world, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return MenuHelper.onOptionsItemSelected(this, item); - } - - @Override - public Context getContext() { - return this; - } - - @Override - public boolean propagateOnOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); - } - @SuppressWarnings("StatementWithEmptyBody") @Override - public boolean onNavigationItemSelected(MenuItem item) { + public boolean onNavigationItemSelected(@NonNull MenuItem item) { // Handle navigation view item clicks here. int id = item.getItemId(); - Log.d("World activity nav-drawer menu item selected: " + id); + Log.d(this, "World activity nav-drawer menu item selected: " + id); - final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + final DrawerLayout drawer = mBinding.drawerLayout; assert drawer != null; - switch (id){ - case(R.id.nav_world_show_map): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openWorldMap(); - } - }); + switch (id) { + case (R.id.nav_world_show_map): + changeContentFragment(this::openWorldMap); break; - case(R.id.nav_world_select): + case (R.id.nav_world_select): //close activity; back to world selection screen closeWorldActivity(); break; - case(R.id.nav_singleplayer_nbt): + case (R.id.nav_singleplayer_nbt): openPlayerEditor(); break; - case(R.id.nav_multiplayer_nbt): + case (R.id.nav_multiplayer_nbt): openMultiplayerEditor(); break; /*case(R.id.nav_inventory): @@ -389,136 +349,103 @@ public void onOpen() { //This feature is planned, but not yet implemented, // use the generic NBT editor for now... break;*/ - case(R.id.nav_world_nbt): + case (R.id.nav_world_nbt): openLevelEditor(); break; /*case(R.id.nav_tools): //TODO open tools menu (world downloader/importer/exporter maybe?) break;*/ - case(R.id.nav_overworld_satellite): + case (R.id.nav_overworld_satellite): changeMapType(MapType.OVERWORLD_SATELLITE, Dimension.OVERWORLD); break; - case(R.id.nav_overworld_cave): + case (R.id.nav_overworld_cave): changeMapType(MapType.OVERWORLD_CAVE, Dimension.OVERWORLD); break; - case(R.id.nav_overworld_slime_chunk): + case (R.id.nav_overworld_slime_chunk): changeMapType(MapType.OVERWORLD_SLIME_CHUNK, Dimension.OVERWORLD); break; /*case(R.id.nav_overworld_debug): changeMapType(MapType.DEBUG); //for debugging tiles positions, rendering, etc. break;*/ - case(R.id.nav_overworld_heightmap): + case (R.id.nav_overworld_heightmap): changeMapType(MapType.OVERWORLD_HEIGHTMAP, Dimension.OVERWORLD); break; - case(R.id.nav_overworld_biome): + case (R.id.nav_overworld_biome): changeMapType(MapType.OVERWORLD_BIOME, Dimension.OVERWORLD); break; - case(R.id.nav_overworld_grass): + case (R.id.nav_overworld_grass): changeMapType(MapType.OVERWORLD_GRASS, Dimension.OVERWORLD); break; - case(R.id.nav_overworld_xray): + case (R.id.nav_overworld_xray): changeMapType(MapType.OVERWORLD_XRAY, Dimension.OVERWORLD); break; - case(R.id.nav_overworld_block_light): + case (R.id.nav_overworld_block_light): changeMapType(MapType.OVERWORLD_BLOCK_LIGHT, Dimension.OVERWORLD); break; - case(R.id.nav_nether_map): + case (R.id.nav_nether_map): changeMapType(MapType.NETHER, Dimension.NETHER); break; - case(R.id.nav_nether_xray): + case (R.id.nav_nether_xray): changeMapType(MapType.NETHER_XRAY, Dimension.NETHER); break; - case(R.id.nav_nether_block_light): + case (R.id.nav_nether_block_light): changeMapType(MapType.NETHER_BLOCK_LIGHT, Dimension.NETHER); break; - case(R.id.nav_end_satellite): + case (R.id.nav_nether_biome): + changeMapType(MapType.NETHER_BIOME, Dimension.NETHER); + break; + case (R.id.nav_end_satellite): changeMapType(MapType.END_SATELLITE, Dimension.END); break; - case(R.id.nav_end_heightmap): + case (R.id.nav_end_heightmap): changeMapType(MapType.END_HEIGHTMAP, Dimension.END); break; - case(R.id.nav_end_block_light): + case (R.id.nav_end_block_light): changeMapType(MapType.END_BLOCK_LIGHT, Dimension.END); break; - case(R.id.nav_map_opt_toggle_grid): + case (R.id.nav_map_opt_toggle_grid): //toggle the grid this.showGrid = !this.showGrid; //rerender tiles (tiles will render with toggled grid on it now) - if(this.mapFragment != null) this.mapFragment.resetTileView(); + if (this.mapFragment != null) this.mapFragment.resetTileView(); break; - case(R.id.nav_map_opt_filter_markers): + case (R.id.nav_map_opt_filter_markers): //toggle the grid + TileEntity.loadIcons(getAssets()); this.mapFragment.openMarkerFilter(); break; - case(R.id.nav_map_opt_toggle_markers): + case (R.id.nav_map_opt_toggle_markers): //toggle markers - if(this.mapFragment != null) this.mapFragment.toggleMarkers(); + showMarkers = !showMarkers; + getPreferences(MODE_PRIVATE).edit() + .putBoolean(PREF_KEY_SHOW_MARKERS, showMarkers).apply(); + if (this.mapFragment != null) this.mapFragment.toggleMarkers(); break; - case(R.id.nav_biomedata_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.BIOME_DATA); - } - }); + case (R.id.nav_biomedata_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.BIOME_DATA)); break; - case(R.id.nav_overworld_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.OVERWORLD); - } - }); + case (R.id.nav_overworld_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.OVERWORLD)); break; - case(R.id.nav_villages_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.M_VILLAGES); - } - }); + case (R.id.nav_villages_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.M_VILLAGES)); break; - case(R.id.nav_portals_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.PORTALS); - } - }); + case (R.id.nav_portals_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.PORTALS)); break; - case(R.id.nav_dimension0_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.DIMENSION_0); - } - }); + case (R.id.nav_dimension0_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.DIMENSION_0)); break; - case(R.id.nav_dimension1_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.DIMENSION_1); - } - }); + case (R.id.nav_dimension1_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.DIMENSION_1)); break; - case(R.id.nav_dimension2_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.DIMENSION_2); - } - }); + case (R.id.nav_dimension2_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.DIMENSION_2)); break; - case(R.id.nav_autonomous_entities_nbt): - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openSpecialDBEntry(World.SpecialDBEntryType.AUTONOMOUS_ENTITIES); - } - }); + case (R.id.nav_autonomous_entities_nbt): + changeContentFragment(() -> openSpecialDBEntry(World.SpecialDBEntryType.AUTONOMOUS_ENTITIES)); break; - case(R.id.nav_open_nbt_by_name): { + case (R.id.nav_open_nbt_by_name): { //TODO put this bit in its own method @@ -530,39 +457,31 @@ public void onOpen() { new AlertDialog.Builder(WorldActivity.this) .setTitle(R.string.open_nbt_from_db) .setView(keyEditText) - .setPositiveButton(R.string.open, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - Editable keyNameEditable = keyEditText.getText(); - String keyName = keyNameEditable == null - ? null : keyNameEditable.toString(); - if(keyName == null || keyName.equals("")){ - Snackbar.make(drawer, - R.string.invalid_keyname, - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } else { - try { - EditableNBT dbEntry = openEditableNbtDbEntry(keyName); - if (dbEntry == null) Snackbar.make(drawer, - R.string.cannot_find_db_entry_with_name, - Snackbar.LENGTH_LONG) - .setAction("Action", null).show();//TODO maybe add option to create it? - else openNBTEditor(dbEntry); - } catch (Exception e){ - Snackbar.make(drawer, - R.string.invalid_keyname, - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - } - } - }); + .setPositiveButton(R.string.open, (dialog, which) -> changeContentFragment(() -> { + Editable keyNameEditable = keyEditText.getText(); + String keyName = keyNameEditable == null + ? null : keyNameEditable.toString(); + if (keyName == null || keyName.equals("")) { + Snackbar.make(drawer, + R.string.invalid_keyname, + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } else { + try { + EditableNBT dbEntry = openEditableNbtDbEntry(keyName); + if (dbEntry == null) Snackbar.make(drawer, + R.string.cannot_find_db_entry_with_name, + Snackbar.LENGTH_LONG) + .setAction("Action", null).show();//TODO maybe add option to create it? + else openNBTEditor(dbEntry); + } catch (Exception e) { + Snackbar.make(drawer, + R.string.invalid_keyname, + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } } - }) + })) .setCancelable(true) .setNegativeButton(android.R.string.cancel, null) .show(); @@ -571,7 +490,7 @@ public void onOpen() { } default: //Warning, we might have messed with the menu XML! - Log.w("pressed unknown navigation-item in world-activity-drawer"); + Log.d(this, "pressed unknown navigation-item in world-activity-drawer"); break; } @@ -600,11 +519,11 @@ public EditableNBT openEditableNbtDbEntry(final String keyName) throws IOExcepti WorldData worldData = world.getWorldData(); try { worldData.openDB(); - } catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); } byte[] entryData = worldData.db.get(keyBytes); - if(entryData == null) return null; + if (entryData == null) return null; final ArrayList workCopy = DataConverter.read(entryData); @@ -651,8 +570,9 @@ public void removeRootTag(Tag tag) { /** * Loads local player data "~local-player" or level.dat>"Player" into an EditableNBT. + * * @return EditableNBT, local player NBT data wrapped in a handle to use for saving + metadata - * @throws Exception + * @throws Exception wtf */ public EditableNBT getEditablePlayer() throws Exception { @@ -670,33 +590,36 @@ public EditableNBT getEditablePlayer() throws Exception { EditableNBT editableNBT; try { editableNBT = openSpecialEditableNbtDbEntry(World.SpecialDBEntryType.LOCAL_PLAYER); - } catch (IOException e){ + } catch (IOException e) { e.printStackTrace(); throw new Exception("Failed to read \"~local_player\" from the database."); } //check if it is not found in the DB - if(editableNBT == null) editableNBT = openEditableNbtLevel("Player"); + if (editableNBT == null) editableNBT = openEditableNbtLevel("Player"); //check if it is not found in level.dat as well - if(editableNBT == null) throw new Exception("Failed to find \"~local_player\" in DB and \"Player\" in level.dat!"); + if (editableNBT == null) + throw new Exception("Failed to find \"~local_player\" in DB and \"Player\" in level.dat!"); return editableNBT; } - /** Open NBT editor fragment for special database entry */ - public void openSpecialDBEntry(final World.SpecialDBEntryType entryType){ + /** + * Open NBT editor fragment for special database entry + */ + public void openSpecialDBEntry(final World.SpecialDBEntryType entryType) { try { EditableNBT editableEntry = openSpecialEditableNbtDbEntry(entryType); - if(editableEntry == null){ + if (editableEntry == null) { this.openWorldMap(); //TODO better handling of db problems //throw new Exception("\"" + entryType.keyName + "\" not found in DB."); } - Log.i("Opening NBT editor for \"" + entryType.keyName + "\" from world database."); + Log.d(this, "Opening NBT editor for \"" + entryType.keyName + "\" from world database."); openNBTEditor(editableEntry); @@ -704,37 +627,30 @@ public void openSpecialDBEntry(final World.SpecialDBEntryType entryType){ e.printStackTrace(); String msg = e.getMessage(); - if(e instanceof IOException) msg = String.format(getString(R.string.failed_to_read_x_from_db), entryType.keyName); + if (e instanceof IOException) + Log.d(this, String.format(getString(R.string.failed_to_read_x_from_db), entryType.keyName)); + else Log.d(this, e); new AlertDialog.Builder(WorldActivity.this) - .setMessage(msg) + .setMessage(msg == null ? "" : msg) .setCancelable(false) - .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openWorldMap(); - } - }); - } - }).show(); + .setNeutralButton(android.R.string.ok, (dialog, id) -> changeContentFragment(() -> openWorldMap())).show(); } } - public void openMultiplayerEditor(){ + public void openMultiplayerEditor() { //takes some time to find all players... // TODO make more responsive // TODO maybe cache player keys for responsiveness? // Or messes this too much with the first perception of present players? - final String[] players = getWorld().getWorldData().getPlayers(); + final String[] players = getWorld().getWorldData().getNetworkPlayerNames(); - final View content = WorldActivity.this.findViewById(R.id.world_content); - if(players.length == 0){ - if(content != null) Snackbar.make(content, + final View content = mBinding.getRoot(); + if (players.length == 0) { + Snackbar.make(content, R.string.no_multiplayer_data_found, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); @@ -766,37 +682,24 @@ public void onClick(DialogInterface dialog, int whichButton) { final EditableNBT editableNBT = WorldActivity.this .openEditableNbtDbEntry(playerKey); - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - try { - openNBTEditor(editableNBT); - } catch (Exception e){ - new AlertDialog.Builder(WorldActivity.this) + changeContentFragment(() -> { + try { + openNBTEditor(editableNBT); + } catch (Exception e) { + new AlertDialog.Builder(WorldActivity.this) .setMessage(e.getMessage()) .setCancelable(false) .setNeutralButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, - int id) { - changeContentFragment( - new OpenFragmentCallback() { - @Override - public void onOpen() { - openWorldMap(); - } - }); - } - }).show(); - } - + (dialog1, id) -> changeContentFragment( + () -> openWorldMap())).show(); } + }); - } catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); - Log.d("Failed to open player entry in DB. key: "+playerKey); - if(content != null) Snackbar.make(content, + Log.d(this, "Failed to open player entry in DB. key: " + playerKey); + if (content != null) Snackbar.make(content, String.format(getString(R.string.failed_read_player_from_db_with_key_x), playerKey), Snackbar.LENGTH_LONG) .setAction("Action", null).show(); @@ -808,52 +711,40 @@ public void onOpen() { .show(); } - public void openPlayerEditor(){ - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - - try { - openNBTEditor(getEditablePlayer()); - } catch (Exception e){ - new AlertDialog.Builder(WorldActivity.this) - .setMessage(e.getMessage()) - .setCancelable(false) - .setNeutralButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openWorldMap(); - } - }); - } - }).show(); - } - + public void openPlayerEditor() { + changeContentFragment(() -> { + try { + openNBTEditor(getEditablePlayer()); + } catch (Exception e) { + new AlertDialog.Builder(WorldActivity.this) + .setMessage(e.getMessage()) + .setCancelable(false) + .setNeutralButton(android.R.string.ok, + (dialog, id) -> changeContentFragment(this::openWorldMap)).show(); } + }); } - /** Opens an editableNBT for just the subTag if it is not null. - Opens the whole level.dat if subTag is null. **/ - public EditableNBT openEditableNbtLevel(String subTagName){ + /** + * Opens an editableNBT for just the subTag if it is not null. + * Opens the whole level.dat if subTag is null. + **/ + public EditableNBT openEditableNbtLevel(String subTagName) { //make a copy first, the user might not want to save changed tags. - final CompoundTag workCopy = world.level.getDeepCopy(); + final CompoundTag workCopy = world.getLevel().getDeepCopy(); final ArrayList workCopyContents; final String contentTitle; - if(subTagName == null){ + if (subTagName == null) { workCopyContents = workCopy.getValue(); contentTitle = "level.dat"; - } - else{ + } else { workCopyContents = new ArrayList<>(); Tag subTag = workCopy.getChildTagByKey(subTagName); - if(subTag == null) return null; + if (subTag == null) return null; workCopyContents.add(subTag); - contentTitle = "level.dat>"+subTagName; + contentTitle = "level.dat>" + subTagName; } EditableNBT editableNBT = new EditableNBT() { @@ -899,13 +790,8 @@ public void removeRootTag(Tag tag) { return editableNBT; } - public void openLevelEditor(){ - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { - openNBTEditor(openEditableNbtLevel(null)); - } - }); + public void openLevelEditor() { + changeContentFragment(() -> openNBTEditor(openEditableNbtLevel(null))); } //TODO the dimension should be derived from mapTypes. @@ -913,13 +799,13 @@ public void onOpen() { // splitting allows to pass more sophisticated use of [MapRenderer]s private Dimension dimension = Dimension.OVERWORLD; - public Dimension getDimension(){ + public Dimension getDimension() { return this.dimension; } private MapType mapType = dimension.defaultMapType; - public MapType getMapType(){ + public MapType getMapType() { return this.mapType; } @@ -929,61 +815,64 @@ public MapType getMapType(){ // which is not an easy task. public boolean showGrid = true; + public boolean showMarkers; + @Override public boolean getShowGrid() { return showGrid; } + @Override + public boolean getShowMarkers() { + return showMarkers; + } + private boolean fatal = false; + @Override public void onFatalDBError(WorldData.WorldDBException worldDBException) { - Log.d(worldDBException.getMessage()); + Log.d(this, worldDBException.getMessage()); worldDBException.printStackTrace(); //already dead? (happens on multiple onFatalDBError(e) calls) - if(fatal) return; + if (fatal) return; fatal = true; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.error_cannot_open_world_close_and_try_again) .setCancelable(false) - .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - WorldActivity.this.finish(); - } - }); + .setNeutralButton(android.R.string.ok, (dialog, id) -> WorldActivity.this.finish()); AlertDialog alert = builder.create(); alert.show(); } @Override - public void changeMapType(MapType mapType, Dimension dimension){ + public void changeMapType(MapType mapType, Dimension dimension) { this.mapType = mapType; this.dimension = dimension; //don't forget to do a reset-tileview, the mapfragment should know of this change ASAP. mapFragment.resetTileView(); } - public void closeWorldActivity(){ + public void closeWorldActivity() { //TODO not translation-friendly new AlertDialog.Builder(this) - .setMessage(R.string.confirm_close_world) - .setCancelable(false) - .setIcon(R.drawable.ic_action_exit) - .setPositiveButton(android.R.string.yes, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { + .setMessage(R.string.confirm_close_world) + .setCancelable(false) + .setIcon(R.drawable.ic_action_exit) + .setPositiveButton(android.R.string.yes, + (dialog, id) -> { //finish this activity + mapFragment.closeChunks(); finish(); - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); + }) + .setNegativeButton(android.R.string.no, null) + .show(); } public interface OpenFragmentCallback { @@ -992,25 +881,23 @@ public interface OpenFragmentCallback { public String confirmContentClose = null; - public void changeContentFragment(final OpenFragmentCallback callback){ + public void changeContentFragment(final OpenFragmentCallback callback) { - final FragmentManager manager = getFragmentManager(); + final FragmentManager manager = getSupportFragmentManager(); // confirmContentClose shouldn't be both used as boolean and as close-message, // this is a bad pattern - if(confirmContentClose != null){ + if (confirmContentClose != null) { new AlertDialog.Builder(this) - .setMessage(confirmContentClose) - .setCancelable(false) - .setPositiveButton(android.R.string.yes, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); - callback.onOpen(); - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); + .setMessage(confirmContentClose) + .setCancelable(false) + .setPositiveButton(android.R.string.yes, + (dialog, id) -> { + manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); + callback.onOpen(); + }) + .setNegativeButton(android.R.string.no, null) + .show(); } else { manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); callback.onOpen(); @@ -1018,16 +905,23 @@ public void onClick(DialogInterface dialog, int id) { } - /** Open NBT editor fragment for the given editableNBT */ - public void openNBTEditor(EditableNBT editableNBT){ + /** + * Open NBT editor fragment for the given editableNBT + */ + public void openNBTEditor(EditableNBT editableNBT) { + + if (editableNBT == null) { + Toast.makeText(this, "Empty data.", Toast.LENGTH_SHORT).show(); + return; + } // see changeContentFragment(callback) this.confirmContentClose = getString(R.string.confirm_close_nbt_editor); EditorFragment editorFragment = new EditorFragment(); - editorFragment.setEditableNBT(editableNBT); + editorFragment.setNbt(editableNBT); - FragmentTransaction transaction = getFragmentManager().beginTransaction(); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.world_content, editorFragment); transaction.addToBackStack(null); @@ -1035,15 +929,17 @@ public void openNBTEditor(EditableNBT editableNBT){ } - /** Replace current content fragment with a fresh MapFragment */ - public void openWorldMap(){ + /** + * Replace current content fragment with a fresh MapFragment + */ + public void openWorldMap() { //TODO should this use cached world-position etc.? this.confirmContentClose = null; this.mapFragment = new MapFragment(); - FragmentTransaction transaction = getFragmentManager().beginTransaction(); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.world_content, this.mapFragment); transaction.commit(); @@ -1057,34 +953,35 @@ public World getWorld() { @Override - public void addMarker(AbstractMarker marker){ + public void addMarker(AbstractMarker marker) { mapFragment.addMarker(marker); } - - /** Open a dialog; user chooses chunk-type -> open editor for this type **/ + /** + * Open a dialog; user chooses chunk-type -> open editor for this type + **/ @Override - public void openChunkNBTEditor(final int chunkX, final int chunkZ, final NBTChunkData nbtChunkData, final ViewGroup viewGroup){ + public void openChunkNBTEditor(final int chunkX, final int chunkZ, final NBTChunkData nbtChunkData, final ViewGroup viewGroup) { - if(nbtChunkData == null){ + if (nbtChunkData == null) { //should never happen - Log.w("User tried to open null chunkData in the nbt-editor!!!"); + Log.e(this, "User tried to open null chunkData in the nbt-editor!!!"); return; } try { nbtChunkData.load(); - } catch (Exception e){ + } catch (Exception e) { Snackbar.make(viewGroup, this.getString(R.string.failed_to_load_x, this.getString(R.string.nbt_chunk_data)), Snackbar.LENGTH_LONG) .setAction("Action", null).show(); return; } final List tags = nbtChunkData.tags; - if(tags == null) { + if (tags == null) { new AlertDialog.Builder(this) .setTitle(R.string.nbt_editor) .setMessage(R.string.data_does_not_exist_for_chunk_ask_if_create) @@ -1092,17 +989,16 @@ public void openChunkNBTEditor(final int chunkX, final int chunkZ, final NBTChun .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - Snackbar.make(viewGroup, R.string.creating_and_saving_chunk_NBT_data, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); nbtChunkData.createEmpty(); try { nbtChunkData.write(); Snackbar.make(viewGroup, R.string.created_and_saved_chunk_NBT_data, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); WorldActivity.this.openChunkNBTEditor(chunkX, chunkZ, nbtChunkData, viewGroup); - } catch (Exception e){ + } catch (Exception e) { Snackbar.make(viewGroup, R.string.failed_to_create_or_save_chunk_NBT_data, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); + Log.d(this, e); } } }) @@ -1112,64 +1008,63 @@ public void onClick(DialogInterface dialog, int whichButton) { } - //open nbt editor for entity data - changeContentFragment(new OpenFragmentCallback() { - @Override - public void onOpen() { + changeContentFragment(() -> { - //make a copy first, the user might not want to save changed tags. - final List workCopy = new ArrayList<>(); - for(Tag tag : tags){ - workCopy.add(tag.getDeepCopy()); - } + //make a copy first, the user might not want to save changed tags. + final List workCopy = new ArrayList<>(); + for (Tag tag : tags) { + workCopy.add(tag.getDeepCopy()); + } - final EditableNBT editableChunkData = new EditableNBT() { + final EditableNBT editableChunkData = new EditableNBT() { - @Override - public Iterable getTags() { - return workCopy; - } + @Override + public Iterable getTags() { + return workCopy; + } - @Override - public boolean save() { - try { - final List saveCopy = new ArrayList<>(); - for(Tag tag : workCopy){ - saveCopy.add(tag.getDeepCopy()); - } - nbtChunkData.tags = saveCopy; - nbtChunkData.write(); - return true; - } catch (Exception e) { - e.printStackTrace(); + @Override + public boolean save() { + try { + final List saveCopy = new ArrayList<>(); + for (Tag tag : workCopy) { + saveCopy.add(tag.getDeepCopy()); } - return false; + nbtChunkData.tags = saveCopy; + nbtChunkData.write(); + return true; + } catch (Exception e) { + e.printStackTrace(); } + return false; + } - @Override - public String getRootTitle() { - final String format = "%s (cX:%d;cZ:%d)"; - switch ((nbtChunkData).dataType){ - case ENTITY: return String.format(format, getString(R.string.entity_chunk_data) , chunkX, chunkZ); - case BLOCK_ENTITY: return String.format(format, getString(R.string.tile_entity_chunk_data), chunkX, chunkZ); - default: return String.format(format, getString(R.string.nbt_chunk_data), chunkX, chunkZ); - } + @Override + public String getRootTitle() { + final String format = "%s (cX:%d;cZ:%d)"; + switch ((nbtChunkData).dataType) { + case ENTITY: + return String.format(format, getString(R.string.entity_chunk_data), chunkX, chunkZ); + case BLOCK_ENTITY: + return String.format(format, getString(R.string.tile_entity_chunk_data), chunkX, chunkZ); + default: + return String.format(format, getString(R.string.nbt_chunk_data), chunkX, chunkZ); } + } - @Override - public void addRootTag(Tag tag) { - workCopy.add(tag); - } + @Override + public void addRootTag(Tag tag) { + workCopy.add(tag); + } - @Override - public void removeRootTag(Tag tag) { - workCopy.remove(tag); - } - }; + @Override + public void removeRootTag(Tag tag) { + workCopy.remove(tag); + } + }; - openNBTEditor(editableChunkData); - } + openNBTEditor(editableChunkData); }); } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivityInterface.java b/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivityInterface.java index 1f1af8c3..512af52d 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivityInterface.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/WorldActivityInterface.java @@ -1,9 +1,7 @@ package com.mithrilmania.blocktopograph; -import android.os.Bundle; - import android.view.ViewGroup; -import com.mithrilmania.blocktopograph.chunk.ChunkData; + import com.mithrilmania.blocktopograph.chunk.NBTChunkData; import com.mithrilmania.blocktopograph.map.Dimension; import com.mithrilmania.blocktopograph.map.marker.AbstractMarker; @@ -23,18 +21,18 @@ public interface WorldActivityInterface { boolean getShowGrid(); + boolean getShowMarkers(); + void onFatalDBError(WorldData.WorldDBException worldDB); void addMarker(AbstractMarker marker); - void logFirebaseEvent(WorldActivity.CustomFirebaseEvent firebaseEvent); - - void logFirebaseEvent(WorldActivity.CustomFirebaseEvent firebaseEvent, Bundle eventContent); - void showActionBar(); void hideActionBar(); + void openDrawer(); + EditableNBT getEditablePlayer() throws Exception; void changeMapType(MapType mapType, Dimension dimension); diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/WorldData.java b/app/src/main/java/com/mithrilmania/blocktopograph/WorldData.java index c9dd8f30..eefd25d0 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/WorldData.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/WorldData.java @@ -1,69 +1,107 @@ package com.mithrilmania.blocktopograph; import android.annotation.SuppressLint; +import android.util.LruCache; +import androidx.annotation.Nullable; + +import com.litl.leveldb.DB; +import com.litl.leveldb.Iterator; +import com.mithrilmania.blocktopograph.block.OldBlockRegistry; +import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.ChunkTag; +import com.mithrilmania.blocktopograph.chunk.Version; import com.mithrilmania.blocktopograph.map.Dimension; -import com.litl.leveldb.Iterator; -import com.litl.leveldb.DB; import java.io.File; -import java.nio.ByteBuffer; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; +import java.util.stream.IntStream; /** * Wrapper around level.dat world spec en levelDB database. */ public class WorldData { - public static class WorldDataLoadException extends Exception { - private static final long serialVersionUID = 659185044124115547L; + //another method for debugging, makes it easy to print a readable byte array + private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); - public WorldDataLoadException(String msg){ super(msg); } - } + public DB db; - public static class WorldDBException extends Exception { - private static final long serialVersionUID = -3299282170140961220L; + private WeakReference world; + private LruCache chunks = new ChunkCache(this, 256); + public final OldBlockRegistry mOldBlockRegistry; - public WorldDBException(String msg){ super(msg); } + public WorldData(World world) { + this.world = new WeakReference<>(world); + this.mOldBlockRegistry = new OldBlockRegistry(2048); } - public static class WorldDBLoadException extends Exception { - private static final long serialVersionUID = 4412238820886423076L; - - public WorldDBLoadException(String msg){ super(msg); } + static String bytesToHex(byte[] bytes, int start, int end) { + char[] hexChars = new char[(end - start) * 2]; + for (int j = start; j < end; j++) { + int v = bytes[j] & 0xFF; + hexChars[(j - start) * 2] = hexArray[v >>> 4]; + hexChars[(j - start) * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); } - private World world; - - public DB db; + private static byte[] getChunkDataKey(int x, int z, ChunkTag type, Dimension dimension, byte subChunk, boolean asSubChunk) { + if (dimension == Dimension.OVERWORLD) { + byte[] key = new byte[asSubChunk ? 10 : 9]; + System.arraycopy(getReversedBytes(x), 0, key, 0, 4); + System.arraycopy(getReversedBytes(z), 0, key, 4, 4); + key[8] = type.dataID; + if (asSubChunk) key[9] = subChunk; + return key; + } else { + byte[] key = new byte[asSubChunk ? 14 : 13]; + System.arraycopy(getReversedBytes(x), 0, key, 0, 4); + System.arraycopy(getReversedBytes(z), 0, key, 4, 4); + System.arraycopy(getReversedBytes(dimension.id), 0, key, 8, 4); + key[12] = type.dataID; + if (asSubChunk) key[13] = subChunk; + return key; + } + } - public WorldData(World world){ - this.world = world; + private static byte[] getReversedBytes(int i) { + return new byte[]{ + (byte) i, + (byte) (i >> 8), + (byte) (i >> 16), + (byte) (i >> 24) + }; } //load db when needed (does not load it!) @SuppressLint({"SetWorldReadable", "SetWorldWritable"}) public void load() throws WorldDataLoadException { - if(db != null) return; + if (db != null) return; - File dbFile = new File(this.world.worldFolder, "db"); - if(!dbFile.canRead()){ - if(!dbFile.setReadable(true, false)) throw new WorldDataLoadException("World-db folder is not readable! World-db folder: "+dbFile.getAbsolutePath()); + World world = this.world.get(); + + File dbFile = new File(world.worldFolder, "db"); + if (!dbFile.canRead()) { + if (!dbFile.setReadable(true, false)) + throw new WorldDataLoadException("World-db folder is not readable! World-db folder: " + dbFile.getAbsolutePath()); } - if(!dbFile.canWrite()){ - if(!dbFile.setWritable(true, false)) throw new WorldDataLoadException("World-db folder is not writable! World-db folder: "+dbFile.getAbsolutePath()); + if (!dbFile.canWrite()) { + if (!dbFile.setWritable(true, false)) + throw new WorldDataLoadException("World-db folder is not writable! World-db folder: " + dbFile.getAbsolutePath()); } - Log.d("WorldFolder: "+this.world.worldFolder.getAbsolutePath()); - Log.d("WorldFolder permissions: read: " + dbFile.canRead() + " write: "+dbFile.canWrite()); + Log.d(this, "WorldFolder: " + world.worldFolder.getAbsolutePath()); + Log.d(this, "WorldFolder permissions: read: " + dbFile.canRead() + " write: " + dbFile.canWrite()); - if(dbFile.listFiles() == null) throw new WorldDataLoadException("Failed loading world-db: cannot list files in worldfolder"); + if (dbFile.listFiles() == null) + throw new WorldDataLoadException("Failed loading world-db: cannot list files in worldfolder"); - for(File dbEntry : dbFile.listFiles()){ - Log.d("File in db: "+dbEntry.getAbsolutePath()); + for (File dbEntry : dbFile.listFiles()) { + Log.d(this, "File in db: " + dbEntry.getAbsolutePath()); } this.db = new DB(dbFile); @@ -72,52 +110,33 @@ public void load() throws WorldDataLoadException { //open db to make it available for this app public void openDB() throws WorldDBException { - if(this.db == null) throw new WorldDBException("DB is null!!! (db is not loaded probably)"); + if (this.db == null) + throw new WorldDBException("DB is null!!! (db is not loaded probably)"); - if(this.db.isClosed()){ - try{ + if (this.db.isClosed()) { + try { this.db.open(); - } catch (Exception e){ + } catch (Exception e) { - throw new WorldDBException("DB could not be opened! "+e.getMessage()); + throw new WorldDBException("DB could not be opened! " + e.getMessage()); } } } - //another method for debugging, makes it easy to print a readable byte array - final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); - public static String bytesToHex(byte[] bytes, int start, int end) { - char[] hexChars = new char[(end-start) * 2]; - for ( int j = start; j < end; j++ ) { - int v = bytes[j] & 0xFF; - hexChars[(j-start) * 2] = hexArray[v >>> 4]; - hexChars[(j-start) * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - //close db to make it available for other apps (Minecraft itself!) public void closeDB() throws WorldDBException { - if(this.db == null) throw new WorldDBException("DB is null!!! (db is not loaded probably)"); - + if (this.db == null) + return; + //Why bother throw an exception, isn't it good enough being able to skip closing as it's null? try { this.db.close(); - } catch (Exception e){ + } catch (Exception e) { //db was already closed (probably) e.printStackTrace(); } } - /** WARNING: DELETES WORLD !!! */ - public void destroy() throws WorldDBException { - if(this.db == null) throw new WorldDBException("DB is null!!! (db is not loaded probably)"); - - this.db.close(); - this.db.destroy(); - this.db = null; - } - public byte[] getChunkData(int x, int z, ChunkTag type, Dimension dimension, byte subChunk, boolean asSubChunk) throws WorldDBException, WorldDBLoadException { //ensure that the db is opened @@ -128,6 +147,10 @@ public byte[] getChunkData(int x, int z, ChunkTag type, Dimension dimension, byt return db.get(chunkKey); } + public byte[] getChunkData(int x, int z, ChunkTag type, Dimension dimension) throws WorldDBException, WorldDBLoadException { + return getChunkData(x, z, type, dimension, (byte) 0, false); + } + public void writeChunkData(int x, int z, ChunkTag type, Dimension dimension, byte subChunk, boolean asSubChunk, byte[] chunkData) throws WorldDBException { //ensure that the db is opened this.openDB(); @@ -142,52 +165,138 @@ public void removeChunkData(int x, int z, ChunkTag type, Dimension dimension, by db.delete(getChunkDataKey(x, z, type, dimension, subChunk, asSubChunk)); } - public String[] getPlayers(){ + public void removeFullChunk(int x, int z, Dimension dimension) { + var iterator = db.iterator(); + int count = 0; + var compareKey = getChunkDataKey(x, z, ChunkTag.DATA_2D, dimension, (byte) 0, false); + int baseKeyLength = dimension == Dimension.OVERWORLD ? 8 : 12; + for (iterator.seekToFirst(); iterator.isValid() && count < 800; iterator.next(), count++) { + byte[] key = iterator.getKey(); + if (key.length > baseKeyLength && key.length <= baseKeyLength + 3 && + IntStream.range(0, baseKeyLength).allMatch(i -> key[i] == compareKey[i])) + db.delete(key); + } + iterator.close(); + } + + public Chunk getChunk(int cX, int cZ, Dimension dimension, boolean createIfMissing, Version createOfVersion) { + Key key = new Key(cX, cZ, dimension); + key.createIfMissng = createIfMissing; + key.createOfVersion = createOfVersion; + return chunks.get(key); + } + + public Chunk getChunk(int cX, int cZ, Dimension dimension) { + Key key = new Key(cX, cZ, dimension); + return chunks.get(key); + } + + // Avoid using cache for stream like operations. + // Caller shall lock cache before operation and invalidate cache afterwards. + public Chunk getChunkStreaming(int cx, int cz, Dimension dimension, boolean createIfMissing, Version createOfVersion) { + return Chunk.create(this, cx, cz, dimension, createIfMissing, createOfVersion); + } + + public void resetCache() { + this.chunks.evictAll(); + } + + public String[] getNetworkPlayerNames() { List players = getDBKeysStartingWith("player_"); - return players.toArray(new String[players.size()]); + return players.toArray(new String[0]); } - public List getDBKeysStartingWith(String startWith){ + public List getDBKeysStartingWith(String startWith) { Iterator it = db.iterator(); ArrayList items = new ArrayList<>(); - for(it.seekToFirst(); it.isValid(); it.next()){ + for (it.seekToFirst(); it.isValid(); it.next()) { byte[] key = it.getKey(); - if(key == null) continue; + if (key == null) continue; String keyStr = new String(key); - if(keyStr.startsWith(startWith)) items.add(keyStr); + if (keyStr.startsWith(startWith)) items.add(keyStr); } it.close(); return items; } - public static byte[] getChunkDataKey(int x, int z, ChunkTag type, Dimension dimension, byte subChunk, boolean asSubChunk){ - if(dimension == Dimension.OVERWORLD) { - byte[] key = new byte[asSubChunk ? 10 : 9]; - System.arraycopy(getReversedBytes(x), 0, key, 0, 4); - System.arraycopy(getReversedBytes(z), 0, key, 4, 4); - key[8] = type.dataID; - if(asSubChunk) key[9] = subChunk; - return key; - } else { - byte[] key = new byte[asSubChunk ? 14 : 13]; - System.arraycopy(getReversedBytes(x), 0, key, 0, 4); - System.arraycopy(getReversedBytes(z), 0, key, 4, 4); - System.arraycopy(getReversedBytes(dimension.id), 0, key, 8, 4); - key[12] = type.dataID; - if(asSubChunk) key[13] = subChunk; - return key; + private static class ChunkCache extends LruCache { + + private WeakReference worldData; + + ChunkCache(WorldData worldData, int maxSize) { + super(maxSize); + this.worldData = new WeakReference<>(worldData); + } + + @Override + protected void entryRemoved(boolean evicted, Key key, Chunk oldValue, Chunk newValue) { + try { + oldValue.save(); + } catch (Exception e) { + Log.d(this, e); + } + } + + @Nullable + @Override + protected Chunk create(Key key) { + WorldData worldData = this.worldData.get(); + if (worldData == null) return null; + return Chunk.create(worldData, key.x, key.z, key.dim, key.createIfMissng, key.createOfVersion); } } - public static byte[] getReversedBytes(int i) { - return new byte[]{ - (byte) i, - (byte) (i >> 8), - (byte) (i >> 16), - (byte) (i >> 24) - }; + static class Key { + + public int x, z; + public Dimension dim; + public boolean createIfMissng; + public Version createOfVersion; + + Key(int x, int z, Dimension dim) { + this.x = x; + this.z = z; + this.dim = dim; + } + + @Override + public int hashCode() { + return (x * 31 + z) * 31 + dim.id; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Key)) return false; + Key another = (Key) obj; + return ((x == another.x) && (z == another.z) && (dim != null) + && (another.dim != null) && (dim.id == another.dim.id)); + } + } + + public static class WorldDataLoadException extends Exception { + private static final long serialVersionUID = 659185044124115547L; + + public WorldDataLoadException(String msg) { + super(msg); + } + } + + public static class WorldDBException extends Exception { + private static final long serialVersionUID = -3299282170140961220L; + + public WorldDBException(String msg) { + super(msg); + } + } + + public static class WorldDBLoadException extends Exception { + private static final long serialVersionUID = 4412238820886423076L; + + public WorldDBLoadException(String msg) { + super(msg); + } } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/WrappedApp.java b/app/src/main/java/com/mithrilmania/blocktopograph/WrappedApp.java new file mode 100644 index 00000000..8ff34849 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/WrappedApp.java @@ -0,0 +1,32 @@ +package com.mithrilmania.blocktopograph; + +import android.app.Application; +import android.content.Intent; + +import androidx.annotation.NonNull; + +public class WrappedApp extends Application implements Thread.UncaughtExceptionHandler { + + private Thread.UncaughtExceptionHandler mDefaultUEhan; + + private boolean mHasUnsatisfiedLinkErrorActivity; + + public WrappedApp() { + mDefaultUEhan = Thread.getDefaultUncaughtExceptionHandler(); + Thread.setDefaultUncaughtExceptionHandler(this); + } + + @Override + public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) { + Log.e(this, throwable); + if (throwable instanceof UnsatisfiedLinkError) { + if (!mHasUnsatisfiedLinkErrorActivity) { + Intent intent = new Intent(this, UnsatisfiedLinkErrorActivity.class); + mHasUnsatisfiedLinkErrorActivity = true; + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } + } + mDefaultUEhan.uncaughtException(thread, throwable); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/backup/Backup.java b/app/src/main/java/com/mithrilmania/blocktopograph/backup/Backup.java new file mode 100644 index 00000000..07c80058 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/backup/Backup.java @@ -0,0 +1,25 @@ +package com.mithrilmania.blocktopograph.backup; + + +import androidx.annotation.NonNull; + +import java.io.File; +import java.util.Date; + +public class Backup { + + public String name; + + public Date time; + + public File file; + + public String size; + + public Backup(@NonNull String name, @NonNull Date time, @NonNull File file, @NonNull String size) { + this.file = file; + this.name = name; + this.time = time; + this.size = size; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/backup/WorldBackups.java b/app/src/main/java/com/mithrilmania/blocktopograph/backup/WorldBackups.java new file mode 100644 index 00000000..2c2bdb1f --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/backup/WorldBackups.java @@ -0,0 +1,189 @@ +package com.mithrilmania.blocktopograph.backup; + +import android.annotation.SuppressLint; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.World; +import com.mithrilmania.blocktopograph.util.IoUtil; + +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.exception.ZipException; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.json.JSONObject; + +import java.io.File; +import java.io.IOException; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.Objects; + +public class WorldBackups { + + public static final String BTG_BACKUPS = "btgBackups"; + private static final String AUTO_BACKUP = "auto_backup"; + private static final String AUTO_DELETE = "auto_delete"; + // We're using this in file name so it should not be location-specific. + @SuppressLint("SimpleDateFormat") + private static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd-HHmm-SSss'-'"); + public boolean autoBackup; + public boolean autoDelete = true; + @NonNull + private World mWorld; + + public WorldBackups(@NonNull World world) { + mWorld = world; + } + + + @NonNull + private File getBackupDir() { + return new File(mWorld.worldFolder, BTG_BACKUPS); + } + + + @NonNull + private File getConfigFile() { + return new File(getBackupDir(), "config.json"); + } + + public void loadConfig() { + File cfg = getConfigFile(); + if (!cfg.isFile()) return; + try { + JSONObject obj = new JSONObject(FileUtils.readFileToString(cfg)); + autoBackup = obj.getBoolean(AUTO_BACKUP); + autoDelete = obj.getBoolean(AUTO_DELETE); + } catch (Exception e) { + Log.d(this, e); + } + } + + public void setAutoBackup(boolean value, @Nullable String readMe) { + if (autoBackup == value) return; + autoBackup = value; + saveConfig(); + if (readMe != null) makeSureReadMeExists(readMe); + } + + public void setAutoDelete(boolean value, @Nullable String readMe) { + if (autoDelete == value) return; + autoDelete = value; + saveConfig(); + if (readMe != null) makeSureReadMeExists(readMe); + } + + public void saveConfig() { + File dir = getBackupDir(); + if (IoUtil.makeSureDirIsDir(dir) != IoUtil.Errno.OK) return; + try { + JSONObject obj = new JSONObject(); + obj.put(AUTO_BACKUP, autoBackup); + obj.put(AUTO_DELETE, autoDelete); + FileUtils.writeStringToFile(getConfigFile(), obj.toString(4)); + } catch (Exception e) { + Log.d(this, e); + } + } + + private void makeSureReadMeExists(String readMe) { + File dir = getBackupDir(); + if (IoUtil.makeSureDirIsDir(dir) != IoUtil.Errno.OK) return; + File file = new File(dir, "readme.txt"); + if (file.exists()) return; + try { + FileUtils.writeStringToFile(file, readMe); + } catch (IOException e) { + Log.d(this, e); + } + } + + public boolean createNewBackup(String name, Date time) { + try { + File bakDir = getBackupDir(); + if (IoUtil.makeSureDirIsDir(bakDir) != IoUtil.Errno.OK) return false; + File zfile = IoUtil.getFileWithFirstAvailableName(bakDir, DATE_FORMAT.format(time) + name, ".zip", "(", ")"); + ZipFile zip = new ZipFile(zfile); + for (File file : Objects.requireNonNull(getFilesInWorldDirExceptBackupDir())) { + if (file.isDirectory()) zip.addFolder(file); + else zip.addFile(file); + } + } catch (Exception e) { + Log.e(this, e); + return false; + } + cleanOldBackups(time); + return true; + } + + public boolean restoreBackup(@NonNull Backup backup) { + ZipFile zip = new ZipFile(backup.file); + if (!zip.isValidZipFile()) return false; + File[] files = getFilesInWorldDirExceptBackupDir(); + if (files == null) return false; + for (File file : files) + if (!FileUtils.deleteQuietly(file)) return false; + try { + zip.extractAll(mWorld.worldFolder.getAbsolutePath()); + } catch (ZipException e) { + Log.d(this, e); + return false; + } + return true; + } + + public boolean deleteBackup(@NonNull Backup backup) { + return backup.file.delete(); + } + + public void cleanOldBackups(@NonNull Date now) { + if (!autoDelete) return; + Backup[] baks = getBackups(); + if (baks == null) return; + for (int count = baks.length - 1; count > 2; count--) { + long diff = (now.getTime() - baks[count].time.getTime()) / 1000L; + long THREE_DAYS = 259200L; + long ONE_YEAR = 31536000L; + if (diff < THREE_DAYS) break; + // Keep old backups. + if (diff < ONE_YEAR) deleteBackup(baks[count]); + } + } + + + @Nullable + private File[] getFilesInWorldDirExceptBackupDir() { + return mWorld.worldFolder.listFiles((file, s) -> !s.equals(BTG_BACKUPS)); + } + + + @Nullable + public Backup[] getBackups() { + File bakDir = getBackupDir(); + if (!bakDir.isDirectory()) return null; + File[] files = bakDir.listFiles((file, s) -> s.endsWith(".zip")); + if (files == null) return null; + Arrays.sort(files); + ArrayUtils.reverse(files); + Backup[] baks = new Backup[files.length]; + for (int i = 0; i < files.length; i++) { + String name = FilenameUtils.getBaseName(files[i].getName()); + ParsePosition pos = new ParsePosition(0); + Date time = DATE_FORMAT.parse(name, pos); + if (time == null) { + time = new Date(0); + } else { + name = name.substring(pos.getIndex()); + } + baks[i] = new Backup(name, time, files[i], FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(files[i]))); + } + return baks; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/Block.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/Block.java new file mode 100644 index 00000000..6c4bb856 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/Block.java @@ -0,0 +1,108 @@ +package com.mithrilmania.blocktopograph.block; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.block.blockproperty.BlockProperty; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public class Block implements Serializable { + + private final String name; + + private final BlockType type; + + private final Object[] knownProperties; + + private final Map customProperties; + + Block(String name, Map customProperties) { + this.name = name; + this.type = null; + this.knownProperties = null; + this.customProperties = customProperties; + } + + Block(BlockType type, Object[] knownProperties, Map customProperties) { + this.name = type.getName(); + this.type = type; + this.knownProperties = knownProperties; + this.customProperties = customProperties; + } + + public String getName() { + return name; + } + + public BlockType getType() { + return type; + } + + public Object getProperty(String name) { + int index = getKnownPropertyIndex(name, type); + if (index >= 0) return knownProperties[index]; + else return customProperties.get(name); + } + + public Object[] getKnownProperties() { + return knownProperties; + } + + public Map getCustomProperties() { + return customProperties; + } + + private static int getKnownPropertyIndex(@NonNull String name, @Nullable BlockType type) { + if (type != null) { + BlockProperty[] properties = type.getKnownProperties(); + for (int i = 0, propertiesLength = properties.length; i < propertiesLength; i++) { + BlockProperty prop = properties[i]; + if (name.equals(prop.getName())) return i; + } + } + return -1; + } + + public static class Builder { + + private final String name; + + private final BlockType type; + + private final Object[] knownProperties; + + private final Map customProperties = new HashMap<>(); + + public Builder(@NonNull String name) { + this.name = name; + this.type = null; + this.knownProperties = null; + } + + public Builder(@NonNull BlockType type) { + this.name = null; + this.type = type; + this.knownProperties = new Object[type.getKnownProperties().length]; + } + + public Builder setProperty(@NonNull String name, Object val) { + int index = getKnownPropertyIndex(name, type); + if (index >= 0) knownProperties[index] = val; + else customProperties.put(name, val); + return this; + } + + public Builder setProperty(@NonNull Tag tag) { + return setProperty(tag.getName(), tag.getValue()); + } + + public Block build() { + if (type == null) return new Block(name, customProperties); + return new Block(type, knownProperties, customProperties); + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockStateBuilder.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockStateBuilder.java new file mode 100644 index 00000000..148a94da --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockStateBuilder.java @@ -0,0 +1,72 @@ +package com.mithrilmania.blocktopograph.block; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; +import com.mithrilmania.blocktopograph.nbt.tags.ByteTag; +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.IntTag; +import com.mithrilmania.blocktopograph.nbt.tags.ShortTag; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; + +import java.util.ArrayList; + +public class BlockStateBuilder { + + private ArrayList tags; + + public BlockStateBuilder() { + tags = new ArrayList<>(); + } + + @NonNull + public BlockStateBuilder addProperty(String name, NBTConstants.NBTType type, int value) { + Tag tag; + switch (type) { + case INT: + tag = new IntTag(name, value); + break; + case SHORT: + tag = new ShortTag(name, (short) value); + break; + case BYTE: + tag = new ByteTag(name, (byte) value); + break; + default: + throw new RuntimeException(); + } + tags.add(tag); + return this; + } + + @NonNull + public BlockStateBuilder addInt(String name, int value) { + tags.add(new IntTag(name, value)); + return this; + } + + @NonNull + public BlockStateBuilder addShort(String name, short value) { + tags.add(new ShortTag(name, value)); + return this; + } + + @NonNull + public BlockStateBuilder addByte(String name, byte value) { + tags.add(new ByteTag(name, value)); + return this; + } + + @NonNull + public BlockStateBuilder addProperty(String name, String value) { + Tag tag; + tags.add(new StringTag(name, value)); + return this; + } + + @NonNull + public CompoundTag build() { + return new CompoundTag("states", tags); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockTemplate.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockTemplate.java new file mode 100644 index 00000000..d7e882db --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockTemplate.java @@ -0,0 +1,48 @@ +package com.mithrilmania.blocktopograph.block; + +import com.mithrilmania.blocktopograph.block.icon.BlockIcon; +import com.mithrilmania.blocktopograph.block.icon.NoBlockIcon; +import com.mithrilmania.blocktopograph.block.icon.TexPathBlockIcon; + +import java.io.Serializable; + +public class BlockTemplate implements Serializable { + + private final String subName; + + private final Block block; + + private final BlockIcon icon; + + private final int color; + + private final boolean hasBiomeShading; + + public BlockTemplate(String subName, Block block, BlockIcon icon, int color, boolean hasBiomeShading) { + this.subName = subName; + this.block = block; + this.icon = icon; + this.color = color; + this.hasBiomeShading = hasBiomeShading; + } + + public String getSubName() { + return subName; + } + + public Block getBlock() { + return block; + } + + public BlockIcon getIcon() { + return icon; + } + + public int getColor() { + return color; + } + + public boolean isHasBiomeShading() { + return hasBiomeShading; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockTemplates.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockTemplates.java new file mode 100644 index 00000000..79e1b6ba --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockTemplates.java @@ -0,0 +1,1704 @@ +package com.mithrilmania.blocktopograph.block; + +import androidx.annotation.NonNull; + +import com.google.common.collect.Streams; +import com.mithrilmania.blocktopograph.block.icon.NoBlockIcon; +import com.mithrilmania.blocktopograph.block.icon.TexPathBlockIcon; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +public class BlockTemplates { + + private static final Map allTemplates = new HashMap<>(); + + private static final BlockTemplate unknownBlockTemplate = new BlockTemplate( + null, new Block.Builder(BlockType.UNKNOWN).build(), + new NoBlockIcon(), 0xff0000, false); + + static { + init(); + } + + private static void init() { + allTemplates.put("minecraft:air", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.AIR).build(), new TexPathBlockIcon(null), 0x00000000, false) + }); + allTemplates.put("minecraft:stone", new BlockTemplate[]{ + new BlockTemplate("stone", new Block.Builder(BlockType.STONE).setProperty("stone_type", "stone").build(), new TexPathBlockIcon("blocks/stone.png"), 0xff464646, false), + new BlockTemplate("granite", new Block.Builder(BlockType.STONE).setProperty("stone_type", "granite").build(), new TexPathBlockIcon("blocks/stone_granite.png"), 0xff8c7167, false), + new BlockTemplate("granite_smooth", new Block.Builder(BlockType.STONE).setProperty("stone_type", "granite_smooth").build(), new TexPathBlockIcon("blocks/stone_granite_smooth.png"), 0xff946251, false), + new BlockTemplate("diorite", new Block.Builder(BlockType.STONE).setProperty("stone_type", "diorite").build(), new TexPathBlockIcon("blocks/stone_diorite.png"), 0xffc6c6c6, false), + new BlockTemplate("diorite_smooth", new Block.Builder(BlockType.STONE).setProperty("stone_type", "diorite_smooth").build(), new TexPathBlockIcon("blocks/stone_diorite_smooth.png"), 0xffbebec1, false), + new BlockTemplate("andesite", new Block.Builder(BlockType.STONE).setProperty("stone_type", "andesite").build(), new TexPathBlockIcon("blocks/stone_andesite.png"), 0xff797777, false), + new BlockTemplate("andesite_smooth", new Block.Builder(BlockType.STONE).setProperty("stone_type", "andesite_smooth").build(), new TexPathBlockIcon("blocks/stone_andesite_smooth.png"), 0xff828382, false) + }); + allTemplates.put("minecraft:grass", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GRASS).build(), new TexPathBlockIcon("blocks/grass_side_carried.png"), 0xff939393, true) + }); + allTemplates.put("minecraft:dirt", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DIRT).setProperty("dirt_type", "normal").build(), new TexPathBlockIcon("blocks/dirt.png"), 0xff866043, true) + }); + allTemplates.put("minecraft:cobblestone", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.COBBLESTONE).build(), new TexPathBlockIcon("blocks/cobblestone.png"), 0xff7a7a7a, false) + }); + allTemplates.put("minecraft:planks", new BlockTemplate[]{ + new BlockTemplate("oak", new Block.Builder(BlockType.PLANKS).setProperty("wood_type", "oak").build(), new TexPathBlockIcon("blocks/planks_oak.png"), 0xff9c7f4e, false), + new BlockTemplate("spruce", new Block.Builder(BlockType.PLANKS).setProperty("wood_type", "spruce").build(), new TexPathBlockIcon("blocks/planks_spruce.png"), 0xff5a3d0d, false), + new BlockTemplate("birch", new Block.Builder(BlockType.PLANKS).setProperty("wood_type", "birch").build(), new TexPathBlockIcon("blocks/planks_birch.png"), 0xffdabd8d, false), + new BlockTemplate("jungle", new Block.Builder(BlockType.PLANKS).setProperty("wood_type", "jungle").build(), new TexPathBlockIcon("blocks/planks_jungle.png"), 0xffBa7d5d, false), + new BlockTemplate("acacia", new Block.Builder(BlockType.PLANKS).setProperty("wood_type", "acacia").build(), new TexPathBlockIcon("blocks/planks_acacia.png"), 0xff934f39, false), + new BlockTemplate("big_oak", new Block.Builder(BlockType.PLANKS).setProperty("wood_type", "dark_oak").build(), new TexPathBlockIcon("blocks/planks_big_oak.png"), 0xff3b260f, false) + }); + allTemplates.put("minecraft:sapling", new BlockTemplate[]{ + new BlockTemplate("oak", new Block.Builder(BlockType.SAPLING).setProperty("sapling_type", "oak").setProperty("age_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/sapling_oak.png"), 0x6b476625, false), + new BlockTemplate("spruce", new Block.Builder(BlockType.SAPLING).setProperty("sapling_type", "spruce").setProperty("age_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/sapling_spruce.png"), 0x53333a21, false), + new BlockTemplate("birch", new Block.Builder(BlockType.SAPLING).setProperty("sapling_type", "birch").setProperty("age_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/sapling_birch.png"), 0x6b769654, false), + new BlockTemplate("jungle", new Block.Builder(BlockType.SAPLING).setProperty("sapling_type", "jungle").setProperty("age_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/sapling_jungle.png"), 0x55305612, false), + new BlockTemplate("acacia", new Block.Builder(BlockType.SAPLING).setProperty("sapling_type", "acacia").setProperty("age_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/sapling_acacia.png"), 0xff718919, false), + new BlockTemplate("big_oak", new Block.Builder(BlockType.SAPLING).setProperty("sapling_type", "dark_oak").setProperty("age_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/sapling_roofed_oak.png"), 0xff6f522d, false) + }); + allTemplates.put("minecraft:bedrock", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BEDROCK).setProperty("infiniburn_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/bedrock.png"), 0xff535353, false) + }); + allTemplates.put("minecraft:flowing_water", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FLOWING_WATER).setProperty("liquid_depth", 0).build(), new TexPathBlockIcon("blocks/water_flow.png"), 0x802e43f4, false) + }); + allTemplates.put("minecraft:water", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WATER).setProperty("liquid_depth", 0).build(), new TexPathBlockIcon("blocks/water_still.png"), 0x802e43f4, false) + }); + allTemplates.put("minecraft:flowing_lava", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FLOWING_LAVA).setProperty("liquid_depth", 0).build(), new TexPathBlockIcon("blocks/lava_flow.png"), 0xf0d45a12, false) + }); + allTemplates.put("minecraft:lava", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LAVA).setProperty("liquid_depth", 0).build(), new TexPathBlockIcon("blocks/lava_still.png"), 0xf0d45a12, false) + }); + allTemplates.put("minecraft:sand", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.SAND).setProperty("sand_type", "normal").build(), new TexPathBlockIcon("blocks/sand.png"), 0xffdbd3a0, false), + new BlockTemplate("red", new Block.Builder(BlockType.SAND).setProperty("sand_type", "red").build(), new TexPathBlockIcon("blocks/red_sand.png"), 0xffa7531f, false) + }); + allTemplates.put("minecraft:gravel", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GRAVEL).build(), new TexPathBlockIcon("blocks/gravel.png"), 0xff7e7c7a, false) + }); + allTemplates.put("minecraft:gold_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GOLD_ORE).build(), new TexPathBlockIcon("blocks/gold_ore.png"), 0xff8f8b7c, false) + }); + allTemplates.put("minecraft:iron_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.IRON_ORE).build(), new TexPathBlockIcon("blocks/iron_ore.png"), 0xff87827e, false) + }); + allTemplates.put("minecraft:coal_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.COAL_ORE).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff737373, false) + }); + allTemplates.put("minecraft:log", new BlockTemplate[]{ + new BlockTemplate("oak", new Block.Builder(BlockType.LOG).setProperty("old_log_type", "oak").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/log_oak.png"), 0xff9a7d4d, false), + new BlockTemplate("spruce", new Block.Builder(BlockType.LOG).setProperty("old_log_type", "spruce").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/log_spruce.png"), 0xff5a3d0d, false), + new BlockTemplate("birch", new Block.Builder(BlockType.LOG).setProperty("old_log_type", "birch").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/log_birch.png"), 0xffdabd8d, false), + new BlockTemplate("jungle", new Block.Builder(BlockType.LOG).setProperty("old_log_type", "jungle").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/log_jungle.png"), 0xffBa7d5d, false) + }); + allTemplates.put("minecraft:leaves", new BlockTemplate[]{ + new BlockTemplate("oak", new Block.Builder(BlockType.LEAVES).setProperty("old_leaf_type", "oak").setProperty("persistent_bit", (byte) 0).setProperty("update_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/leaves_oak.png"), 0xff878787, true), + new BlockTemplate("spruce", new Block.Builder(BlockType.LEAVES).setProperty("old_leaf_type", "spruce").setProperty("persistent_bit", (byte) 0).setProperty("update_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/leaves_spruce.png"), 0xff132613, true), + new BlockTemplate("birch", new Block.Builder(BlockType.LEAVES).setProperty("old_leaf_type", "birch").setProperty("persistent_bit", (byte) 0).setProperty("update_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/leaves_birch.png"), 0xff283816, true), + new BlockTemplate("jungle", new Block.Builder(BlockType.LEAVES).setProperty("old_leaf_type", "jungle").setProperty("persistent_bit", (byte) 0).setProperty("update_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/leaves_jungle.png"), 0xff918e86, true) + }); + allTemplates.put("minecraft:sponge", new BlockTemplate[]{ + new BlockTemplate("dry", new Block.Builder(BlockType.SPONGE).setProperty("sponge_type", "dry").build(), new TexPathBlockIcon("blocks/sponge_dry.png"), 0xffb6b639, false), + new BlockTemplate("wet", new Block.Builder(BlockType.SPONGE).setProperty("sponge_type", "wet").build(), new TexPathBlockIcon("blocks/sponge_wet.png"), 0xff9b9a33, false) + }); + allTemplates.put("minecraft:glass", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GLASS).build(), new TexPathBlockIcon("blocks/glass.png"), 0x46daf0f4, false) + }); + allTemplates.put("minecraft:lapis_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LAPIS_ORE).build(), new TexPathBlockIcon("blocks/lapis_ore.png"), 0xff667086, false) + }); + allTemplates.put("minecraft:lapis_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LAPIS_BLOCK).build(), new TexPathBlockIcon("blocks/lapis_block.png"), 0xff1d47a5, false) + }); + allTemplates.put("minecraft:dispenser", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DISPENSER).setProperty("facing_direction", 0).setProperty("triggered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/dispenser.png"), 0xff606060, false) + }); + allTemplates.put("minecraft:sandstone", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.SANDSTONE).setProperty("sand_stone_type", "default").build(), new TexPathBlockIcon("blocks/sandstone_default.png"), 0xffdad29e, false), + new BlockTemplate("chiseled", new Block.Builder(BlockType.SANDSTONE).setProperty("sand_stone_type", "heiroglyphs").build(), new TexPathBlockIcon("blocks/sandstone_chiseled.png"), 0xffdad1a2, false), + new BlockTemplate("smooth", new Block.Builder(BlockType.SANDSTONE).setProperty("sand_stone_type", "cut").build(), new TexPathBlockIcon("blocks/sandstone_smooth.png"), 0xffdad1a2, false) + }); + allTemplates.put("minecraft:noteblock", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.NOTEBLOCK).build(), new TexPathBlockIcon("blocks/noteblock.png"), 0xff644332, false) + }); + allTemplates.put("minecraft:bed", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BED).setProperty("direction", 0).setProperty("head_piece_bit", (byte) 0).setProperty("occupied_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/bed.png"), 0xff8e1616, false) + }); + allTemplates.put("minecraft:golden_rail", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GOLDEN_RAIL).setProperty("rail_direction", 0).setProperty("rail_data_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/golden_rail.png"), 0xab9a6846, false) + }); + allTemplates.put("minecraft:detector_rail", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DETECTOR_RAIL).setProperty("rail_direction", 0).setProperty("rail_data_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/detector_rail.png"), 0x9b786559, false) + }); + allTemplates.put("minecraft:sticky_piston", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STICKY_PISTON).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/sticky_piston.png"), 0xff8d9263, false) + }); + allTemplates.put("minecraft:web", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WEB).build(), new TexPathBlockIcon("blocks/web.png"), 0x68dcdcdc, false) + }); + allTemplates.put("minecraft:tallgrass", new BlockTemplate[]{ + new BlockTemplate("fern", new Block.Builder(BlockType.TALLGRASS).setProperty("tall_grass_type", "tall").build(), new TexPathBlockIcon("blocks/tallgrass_fern.png"), 0xff747474, true), + new BlockTemplate("grass", new Block.Builder(BlockType.TALLGRASS).setProperty("tall_grass_type", "fern").build(), new TexPathBlockIcon("blocks/tallgrass_grass.png"), 0x4e787878, true) + }); + allTemplates.put("minecraft:deadbush", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DEADBUSH).build(), new TexPathBlockIcon("blocks/deadbush.png"), 0x517b4f19, false) + }); + allTemplates.put("minecraft:piston", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PISTON).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/piston.png"), 0xff998159, false) + }); + allTemplates.put("minecraft:pistonArmCollision", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PISTONARMCOLLISION).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/pistonArmCollision.png"), 0xff9c7f4e, false) + }); + allTemplates.put("minecraft:wool", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.WOOL).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/wool_colored_white.png"), 0xffdddddd, false), + new BlockTemplate("orange", new Block.Builder(BlockType.WOOL).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/wool_colored_orange.png"), 0xffdb7d3e, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.WOOL).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/wool_colored_magenta.png"), 0xffb350bc, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.WOOL).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/wool_colored_light_blue.png"), 0xff6a8ac9, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.WOOL).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/wool_colored_yellow.png"), 0xffb1a627, false), + new BlockTemplate("lime", new Block.Builder(BlockType.WOOL).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/wool_colored_lime.png"), 0xff41ae38, false), + new BlockTemplate("pink", new Block.Builder(BlockType.WOOL).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/wool_colored_pink.png"), 0xffd08499, false), + new BlockTemplate("gray", new Block.Builder(BlockType.WOOL).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/wool_colored_gray.png"), 0xff404040, false), + new BlockTemplate("silver", new Block.Builder(BlockType.WOOL).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/wool_colored_silver.png"), 0xff9aa1a1, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.WOOL).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/wool_colored_cyan.png"), 0xff2e6e89, false), + new BlockTemplate("purple", new Block.Builder(BlockType.WOOL).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/wool_colored_purple.png"), 0xff7e3db5, false), + new BlockTemplate("blue", new Block.Builder(BlockType.WOOL).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/wool_colored_blue.png"), 0xff2e388d, false), + new BlockTemplate("brown", new Block.Builder(BlockType.WOOL).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/wool_colored_brown.png"), 0xff4f321f, false), + new BlockTemplate("green", new Block.Builder(BlockType.WOOL).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/wool_colored_green.png"), 0xff35461b, false), + new BlockTemplate("red", new Block.Builder(BlockType.WOOL).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/wool_colored_red.png"), 0xff963430, false), + new BlockTemplate("black", new Block.Builder(BlockType.WOOL).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/wool_colored_black.png"), 0xff191616, false) + }); + allTemplates.put("minecraft:element_0", new BlockTemplate[]{ + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false), + new BlockTemplate("unknown", new Block.Builder(BlockType.ELEMENT_0).build(), new TexPathBlockIcon("blocks/coal_ore.png"), 0xff191616, false) + }); + allTemplates.put("minecraft:yellow_flower", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.YELLOW_FLOWER).build(), new TexPathBlockIcon("blocks/yellow_flower.png"), 0x1e6ca200, false) + }); + allTemplates.put("minecraft:red_flower", new BlockTemplate[]{ + new BlockTemplate("poppy", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "poppy").build(), new TexPathBlockIcon("blocks/flower_poppy.png"), 0x1d8a2b0d, false), + new BlockTemplate("blue_orchid", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "orchid").build(), new TexPathBlockIcon("blocks/flower_blue_orchid.png"), 0x1d188fd3, false), + new BlockTemplate("allium", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "allium").build(), new TexPathBlockIcon("blocks/flower_allium.png"), 0x1ddbb7f8, false), + new BlockTemplate("houstonia", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "houstonia").build(), new TexPathBlockIcon("blocks/flower_houstonia.png"), 0x1defef99, false), + new BlockTemplate("tulip_red", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "tulip_red").build(), new TexPathBlockIcon("blocks/flower_tulip_red.png"), 0x1dbd2604, false), + new BlockTemplate("tulip_orange", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "tulip_orange").build(), new TexPathBlockIcon("blocks/flower_tulip_orange.png"), 0x1dd06713, false), + new BlockTemplate("tulip_white", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "tulip_white").build(), new TexPathBlockIcon("blocks/flower_tulip_white.png"), 0x1df9f9f9, false), + new BlockTemplate("tulip_pink", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "tulip_pink").build(), new TexPathBlockIcon("blocks/flower_tulip_pink.png"), 0x1dbeb3be, false), + new BlockTemplate("oxeye_daisy", new Block.Builder(BlockType.RED_FLOWER).setProperty("flower_type", "oxeye").build(), new TexPathBlockIcon("blocks/flower_oxeye_daisy.png"), 0x1ddadada, false) + }); + allTemplates.put("minecraft:brown_mushroom", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BROWN_MUSHROOM).build(), new TexPathBlockIcon("blocks/brown_mushroom.png"), 0x198a6953, false) + }); + allTemplates.put("minecraft:red_mushroom", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.RED_MUSHROOM).build(), new TexPathBlockIcon("blocks/red_mushroom.png"), 0x21c33538, false) + }); + allTemplates.put("minecraft:gold_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GOLD_BLOCK).build(), new TexPathBlockIcon("blocks/gold_block.png"), 0xfff9ec4e, false) + }); + allTemplates.put("minecraft:iron_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.IRON_BLOCK).build(), new TexPathBlockIcon("blocks/iron_block.png"), 0xffdbdbdb, false) + }); + allTemplates.put("minecraft:double_stone_slab", new BlockTemplate[]{ + new BlockTemplate("stone", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "smooth_stone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_stone.png"), 0xff9f9f9f, false), + new BlockTemplate("sand", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "sandstone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_sand.png"), 0xffdad29e, false), + new BlockTemplate("wood", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "wood").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_wood.png"), 0xff9c7f4e, false), + new BlockTemplate("cobble", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "cobblestone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_cobble.png"), 0xff7a7a7a, false), + new BlockTemplate("brick", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "brick").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_brick.png"), 0xff926356, false), + new BlockTemplate("smooth_stone_brick", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "stone_brick").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_smooth_stone_brick.png"), 0xff7d7d7d, false), + new BlockTemplate("quartz", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "quartz").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_quartz.png"), 0xff2c161a, false), + new BlockTemplate("nether_brick", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "nether_brick").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab_nether_brick.png"), 0xffece9e2, false), + new BlockTemplate("red_sandstone", new Block.Builder(BlockType.DOUBLE_STONE_SLAB).setProperty("stone_slab_type", "smooth_stone").setProperty("top_slot_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/double_stone_slab_red_sandstone.png"), 0xff9f9f9f, false) + }); + allTemplates.put("minecraft:stone_slab", new BlockTemplate[]{ + new BlockTemplate("stone", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "smooth_stone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xff9f9f9f, false), + new BlockTemplate("sand", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "sandstone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xffdad29e, false), + new BlockTemplate("wood", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "wood").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xff9c7f4e, false), + new BlockTemplate("cobble", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "cobblestone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xff7a7a7a, false), + new BlockTemplate("brick", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "brick").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xff926356, false), + new BlockTemplate("smooth_stone_brick", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "stone_brick").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xff7d7d7d, false), + new BlockTemplate("quartz", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "quartz").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xff2c161a, false), + new BlockTemplate("nether_brick", new Block.Builder(BlockType.STONE_SLAB).setProperty("stone_slab_type", "nether_brick").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab_side.png"), 0xffece9e2, false) + }); + allTemplates.put("minecraft:brick_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BRICK_BLOCK).build(), new TexPathBlockIcon("blocks/brick_block.png"), 0xff926356, false) + }); + allTemplates.put("minecraft:tnt", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.TNT).setProperty("allow_underwater_bit", (byte) 0).setProperty("explode_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/tnt.png"), 0xff82412f, false) + }); + allTemplates.put("minecraft:bookshelf", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BOOKSHELF).build(), new TexPathBlockIcon("blocks/bookshelf.png"), 0xff6b5839, false) + }); + allTemplates.put("minecraft:mossy_cobblestone", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.MOSSY_COBBLESTONE).build(), new TexPathBlockIcon("blocks/mossy_cobblestone.png"), 0xff677967, false) + }); + allTemplates.put("minecraft:obsidian", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.OBSIDIAN).build(), new TexPathBlockIcon("blocks/obsidian.png"), 0xff14121d, false) + }); + allTemplates.put("minecraft:torch", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.TORCH).setProperty("torch_facing_direction", "unknown").build(), new TexPathBlockIcon("blocks/torch.png"), 0x13826a3a, false) + }); + allTemplates.put("minecraft:fire", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FIRE).setProperty("age", 0).build(), new TexPathBlockIcon("blocks/fire.png"), 0x8bd38c35, false) + }); + allTemplates.put("minecraft:mob_spawner", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.MOB_SPAWNER).build(), new TexPathBlockIcon("blocks/mob_spawner.png"), 0x9b1a2731, false) + }); + allTemplates.put("minecraft:oak_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.OAK_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/oak_stairs.png"), 0xff9c7f4e, false) + }); + allTemplates.put("minecraft:chest", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CHEST).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/chest_front.png"), 0xc86f5739, false) + }); + allTemplates.put("minecraft:redstone_wire", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.REDSTONE_WIRE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/redstone_wire.png"), 0x80fa1010, false) + }); + allTemplates.put("minecraft:diamond_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DIAMOND_ORE).build(), new TexPathBlockIcon("blocks/diamond_ore.png"), 0xff818c8f, false) + }); + allTemplates.put("minecraft:diamond_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DIAMOND_BLOCK).build(), new TexPathBlockIcon("blocks/diamond_block.png"), 0xff61dbd5, false) + }); + allTemplates.put("minecraft:crafting_table", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CRAFTING_TABLE).build(), new TexPathBlockIcon("blocks/crafting_table.png"), 0xff6b472a, false) + }); + allTemplates.put("minecraft:wheat", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WHEAT).setProperty("growth", 0).build(), new TexPathBlockIcon("blocks/wheat.png"), 0x0500b312, false) + }); + allTemplates.put("minecraft:farmland", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FARMLAND).setProperty("moisturized_amount", 0).build(), new TexPathBlockIcon("blocks/farmland.png"), 0xff734b2d, false) + }); + allTemplates.put("minecraft:furnace", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FURNACE).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/furnace.png"), 0xff606060, false) + }); + allTemplates.put("minecraft:lit_furnace", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LIT_FURNACE).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/lit_furnace.png"), 0xff606060, false) + }); + allTemplates.put("minecraft:standing_sign", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STANDING_SIGN).setProperty("ground_sign_direction", 0).build(), new TexPathBlockIcon("blocks/standing_sign.png"), 0x566f5739, false) + }); + allTemplates.put("minecraft:wooden_door", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WOODEN_DOOR).setProperty("direction", 0).setProperty("door_hinge_bit", (byte) 0).setProperty("open_bit", (byte) 0).setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_door.png"), 0xcf866733, false) + }); + allTemplates.put("minecraft:ladder", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LADDER).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/ladder.png"), 0x8f795f34, false) + }); + allTemplates.put("minecraft:rail", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.RAIL).setProperty("rail_direction", 0).build(), new TexPathBlockIcon("blocks/rail.png"), 0x8f796c58, false) + }); + allTemplates.put("minecraft:stone_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STONE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_stairs.png"), 0xff7a7a7a, false) + }); + allTemplates.put("minecraft:wall_sign", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WALL_SIGN).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/wall_sign.png"), 0x206f5739, false) + }); + allTemplates.put("minecraft:lever", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LEVER).setProperty("lever_direction", "down_east_west").setProperty("open_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/lever.png"), 0x136a5940, false) + }); + allTemplates.put("minecraft:stone_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STONE_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/stone_pressure_plate.png"), 0xff7d7d7d, false) + }); + allTemplates.put("minecraft:iron_door", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.IRON_DOOR).setProperty("direction", 0).setProperty("door_hinge_bit", (byte) 0).setProperty("open_bit", (byte) 0).setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/iron_door.png"), 0xcfbababa, false) + }); + allTemplates.put("minecraft:wooden_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WOODEN_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/wooden_pressure_plate.png"), 0xff9c7f4e, false) + }); + allTemplates.put("minecraft:redstone_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.REDSTONE_ORE).build(), new TexPathBlockIcon("blocks/redstone_ore.png"), 0xff846b6b, false) + }); + allTemplates.put("minecraft:lit_redstone_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LIT_REDSTONE_ORE).build(), new TexPathBlockIcon("blocks/lit_redstone_ore.png"), 0xff846b6b, false) + }); + allTemplates.put("minecraft:unlit_redstone_torch", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:redstone_torch", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.REDSTONE_TORCH).setProperty("torch_facing_direction", "unknown").build(), new TexPathBlockIcon("blocks/redstone_torch.png"), 0x46a74b29, false) + }); + allTemplates.put("minecraft:stone_button", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STONE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_button.png"), 0x28565656, false) + }); + allTemplates.put("minecraft:snow_layer", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SNOW_LAYER).setProperty("covered_bit", (byte) 0).setProperty("height", 0).build(), new TexPathBlockIcon("blocks/snow_layer.png"), 0xffeffbfb, false) + }); + allTemplates.put("minecraft:ice", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ICE).build(), new TexPathBlockIcon("blocks/ice.png"), 0x9f7dadff, false) + }); + allTemplates.put("minecraft:snow", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SNOW).build(), new TexPathBlockIcon("blocks/snow.png"), 0xffeffbfb, false) + }); + allTemplates.put("minecraft:cactus", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CACTUS).setProperty("age", 0).build(), new TexPathBlockIcon("blocks/cactus.png"), 0xc30d6318, false) + }); + allTemplates.put("minecraft:clay", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CLAY).build(), new TexPathBlockIcon("blocks/clay.png"), 0xff9ea4b0, false) + }); + allTemplates.put("minecraft:reeds", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.REEDS).setProperty("age", 0).build(), new TexPathBlockIcon("blocks/reeds.png"), 0x8c94c065, false) + }); + allTemplates.put("minecraft:jukebox", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.JUKEBOX).build(), new TexPathBlockIcon("blocks/fence_birch_fence.png"), 0x8f463822, false) + }); + allTemplates.put("minecraft:fence", new BlockTemplate[]{ + new BlockTemplate("fence", new Block.Builder(BlockType.FENCE).setProperty("wood_type", "oak").build(), new TexPathBlockIcon("blocks/fence_fence.png"), 0x8f463822, false), + new BlockTemplate("spruce_fence", new Block.Builder(BlockType.FENCE).setProperty("wood_type", "spruce").build(), new TexPathBlockIcon("blocks/fence_spruce_fence.png"), 0x8f5a3d0d, false), + new BlockTemplate("birch_fence", new Block.Builder(BlockType.FENCE).setProperty("wood_type", "birch").build(), new TexPathBlockIcon("blocks/fence_birch_fence.png"), 0x8fdabd8d, false), + new BlockTemplate("jungle_fence", new Block.Builder(BlockType.FENCE).setProperty("wood_type", "jungle").build(), new TexPathBlockIcon("blocks/fence_jungle_fence.png"), 0x8fBa7d5d, false), + new BlockTemplate("acacia_fence", new Block.Builder(BlockType.FENCE).setProperty("wood_type", "acacia").build(), new TexPathBlockIcon("blocks/fence_acacia_fence.png"), 0x8f934f39, false), + new BlockTemplate("dark_oak_fence", new Block.Builder(BlockType.FENCE).setProperty("wood_type", "dark_oak").build(), new TexPathBlockIcon("blocks/fence_dark_oak_fence.png"), 0x8f2d2213, false) + }); + allTemplates.put("minecraft:pumpkin", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PUMPKIN).setProperty("direction", 0).build(), new TexPathBlockIcon("blocks/pumpkin.png"), 0xffc07615, false) + }); + allTemplates.put("minecraft:netherrack", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.NETHERRACK).build(), new TexPathBlockIcon("blocks/netherrack.png"), 0xff6f3634, false) + }); + allTemplates.put("minecraft:soul_sand", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SOUL_SAND).build(), new TexPathBlockIcon("blocks/soul_sand.png"), 0xff544033, false) + }); + allTemplates.put("minecraft:glowstone", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GLOWSTONE).build(), new TexPathBlockIcon("blocks/glowstone.png"), 0xff8f7645, false) + }); + allTemplates.put("minecraft:portal", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PORTAL).setProperty("portal_axis", "unknown").build(), new TexPathBlockIcon("blocks/portal.png"), 0xc8410491, false) + }); + allTemplates.put("minecraft:lit_pumpkin", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LIT_PUMPKIN).setProperty("direction", 0).build(), new TexPathBlockIcon("blocks/lit_pumpkin.png"), 0xffc07615, false) + }); + allTemplates.put("minecraft:cake", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CAKE).setProperty("bite_counter", 0).build(), new TexPathBlockIcon("blocks/cake.png"), 0xc3e4cdce, false) + }); + allTemplates.put("minecraft:unpowered_repeater", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.UNPOWERED_REPEATER).setProperty("direction", 0).setProperty("repeater_delay", 0).build(), new TexPathBlockIcon("blocks/unpowered_repeater.png"), 0xff979393, false) + }); + allTemplates.put("minecraft:powered_repeater", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:invisibleBedrock", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.INVISIBLEBEDROCK).build(), new TexPathBlockIcon("blocks/invisibleBedrock.png"), 0x3c282828, false) + }); + allTemplates.put("minecraft:trapdoor", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/trapdoor.png"), 0xdb7e5d2d, false) + }); + allTemplates.put("minecraft:monster_egg", new BlockTemplate[]{ + new BlockTemplate("stone", new Block.Builder(BlockType.MONSTER_EGG).setProperty("monster_egg_stone_type", "stone").build(), new TexPathBlockIcon("blocks/monster_egg_stone.png"), 0xff7d7d7d, false), + new BlockTemplate("cobble", new Block.Builder(BlockType.MONSTER_EGG).setProperty("monster_egg_stone_type", "cobblestone").build(), new TexPathBlockIcon("blocks/monster_egg_cobble.png"), 0xff7a7a7a, false), + new BlockTemplate("brick", new Block.Builder(BlockType.MONSTER_EGG).setProperty("monster_egg_stone_type", "stone_brick").build(), new TexPathBlockIcon("blocks/monster_egg_brick.png"), 0xff7a7a7a, false), + new BlockTemplate("mossybrick", new Block.Builder(BlockType.MONSTER_EGG).setProperty("monster_egg_stone_type", "mossy_stone_brick").build(), new TexPathBlockIcon("blocks/monster_egg_mossybrick.png"), 0xff7b6651, false), + new BlockTemplate("crackedbrick", new Block.Builder(BlockType.MONSTER_EGG).setProperty("monster_egg_stone_type", "cracked_stone_brick").build(), new TexPathBlockIcon("blocks/monster_egg_crackedbrick.png"), 0xff7b6651, false), + new BlockTemplate("chiseledbrick", new Block.Builder(BlockType.MONSTER_EGG).setProperty("monster_egg_stone_type", "chiseled_stone_brick").build(), new TexPathBlockIcon("blocks/monster_egg_chiseledbrick.png"), 0xff7b6651, false) + }); + allTemplates.put("minecraft:stonebrick", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.STONEBRICK).setProperty("stone_brick_type", "default").build(), new TexPathBlockIcon("blocks/stonebrick_default.png"), 0xff7a7a7a, false), + new BlockTemplate("mossy", new Block.Builder(BlockType.STONEBRICK).setProperty("stone_brick_type", "mossy").build(), new TexPathBlockIcon("blocks/stonebrick_mossy.png"), 0xff72776a, false), + new BlockTemplate("cracked", new Block.Builder(BlockType.STONEBRICK).setProperty("stone_brick_type", "cracked").build(), new TexPathBlockIcon("blocks/stonebrick_cracked.png"), 0xff767676, false), + new BlockTemplate("chiseled", new Block.Builder(BlockType.STONEBRICK).setProperty("stone_brick_type", "chiseled").build(), new TexPathBlockIcon("blocks/stonebrick_chiseled.png"), 0xff767676, false), + new BlockTemplate("smooth", new Block.Builder(BlockType.STONEBRICK).setProperty("stone_brick_type", "smooth").build(), new TexPathBlockIcon("blocks/stonebrick_smooth.png"), 0xff767676, false) + }); + allTemplates.put("minecraft:brown_mushroom_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BROWN_MUSHROOM_BLOCK).setProperty("huge_mushroom_bits", 0).build(), new TexPathBlockIcon("blocks/brown_mushroom_block.png"), 0xff8d6a53, false) + }); + allTemplates.put("minecraft:red_mushroom_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.RED_MUSHROOM_BLOCK).setProperty("huge_mushroom_bits", 0).build(), new TexPathBlockIcon("blocks/red_mushroom_block.png"), 0xffb62524, false) + }); + allTemplates.put("minecraft:iron_bars", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.IRON_BARS).build(), new TexPathBlockIcon("blocks/iron_bars.png"), 0x736d6c6a, false) + }); + allTemplates.put("minecraft:glass_pane", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GLASS_PANE).build(), new TexPathBlockIcon("blocks/glass_pane.png"), 0x1fd3eff4, false) + }); + allTemplates.put("minecraft:melon_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.MELON_BLOCK).build(), new TexPathBlockIcon("blocks/melon_block.png"), 0xff979924, false) + }); + allTemplates.put("minecraft:pumpkin_stem", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PUMPKIN_STEM).setProperty("growth", 0).build(), new TexPathBlockIcon("blocks/pumpkin_stem.png"), 0x1e87b759, false) + }); + allTemplates.put("minecraft:melon_stem", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.MELON_STEM).setProperty("growth", 0).build(), new TexPathBlockIcon("blocks/melon_stem.png"), 0x1e87b759, false) + }); + allTemplates.put("minecraft:vine", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.VINE).setProperty("vine_direction_bits", 0).build(), new TexPathBlockIcon("blocks/vine.png"), 0x8a6f6f6f, false) + }); + allTemplates.put("minecraft:fence_gate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FENCE_GATE).setProperty("direction", 0).setProperty("in_wall_bit", (byte) 0).setProperty("open_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/fence_gate.png"), 0x7b463822, false) + }); + allTemplates.put("minecraft:brick_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BRICK_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/brick_stairs.png"), 0xff926356, false) + }); + allTemplates.put("minecraft:stone_brick_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STONE_BRICK_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_brick_stairs.png"), 0xff7a7a7a, false) + }); + allTemplates.put("minecraft:mycelium", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.MYCELIUM).build(), new TexPathBlockIcon("blocks/mycelium.png"), 0xff6f6369, false) + }); + allTemplates.put("minecraft:waterlily", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WATERLILY).build(), new TexPathBlockIcon("blocks/waterlily.png"), 0x93335a21, false) + }); + allTemplates.put("minecraft:nether_brick", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.NETHER_BRICK).build(), new TexPathBlockIcon("blocks/nether_brick.png"), 0xff2c161a, false) + }); + allTemplates.put("minecraft:nether_brick_fence", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.NETHER_BRICK_FENCE).build(), new TexPathBlockIcon("blocks/nether_brick_fence.png"), 0xff2c161a, false) + }); + allTemplates.put("minecraft:nether_brick_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.NETHER_BRICK_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/nether_brick_stairs.png"), 0xff2c161a, false) + }); + allTemplates.put("minecraft:nether_wart", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.NETHER_WART).setProperty("age", 0).build(), new TexPathBlockIcon("blocks/nether_wart.png"), 0x2a6a0e1e, false) + }); + allTemplates.put("minecraft:enchanting_table", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ENCHANTING_TABLE).build(), new TexPathBlockIcon("blocks/enchanting_table.png"), 0xff67403b, false) + }); + allTemplates.put("minecraft:brewing_stand", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BREWING_STAND).setProperty("brewing_stand_slot_a_bit", (byte) 0).setProperty("brewing_stand_slot_b_bit", (byte) 0).setProperty("brewing_stand_slot_c_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/brewing_stand.png"), 0x767c6751, false) + }); + allTemplates.put("minecraft:cauldron", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CAULDRON).setProperty("cauldron_liquid", "water").setProperty("fill_level", 0).build(), new TexPathBlockIcon("blocks/cauldron.png"), 0xff373737, false) + }); + allTemplates.put("minecraft:end_portal", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.END_PORTAL).build(), new TexPathBlockIcon("blocks/endframe_top.png"), 0xff101010, false) + }); + allTemplates.put("minecraft:end_portal_frame", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.END_PORTAL_FRAME).setProperty("direction", 0).setProperty("end_portal_eye_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/endframe_side.png"), 0xff597560, false) + }); + allTemplates.put("minecraft:end_stone", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.END_STONE).build(), new TexPathBlockIcon("blocks/end_stone.png"), 0xffdddfa5, false) + }); + allTemplates.put("minecraft:dragon_egg", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DRAGON_EGG).build(), new TexPathBlockIcon("blocks/dragon_egg.png"), 0xff0c090f, false) + }); + allTemplates.put("minecraft:redstone_lamp", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.REDSTONE_LAMP).build(), new TexPathBlockIcon("blocks/redstone_lamp.png"), 0xff462b1a, false) + }); + allTemplates.put("minecraft:lit_redstone_lamp", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:dropper", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DROPPER).setProperty("facing_direction", 0).setProperty("triggered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/dropper.png"), 0xff9c7f4e, false) + }); + allTemplates.put("minecraft:activator_rail", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ACTIVATOR_RAIL).setProperty("rail_direction", 0).setProperty("rail_data_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/activator_rail.png"), 0xff9c7f4e, false) + }); + allTemplates.put("minecraft:cocoa", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:sandstone_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SANDSTONE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/sandstone_stairs.png"), 0xffdad29e, false) + }); + allTemplates.put("minecraft:emerald_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.EMERALD_ORE).build(), new TexPathBlockIcon("blocks/emerald_ore.png"), 0xff6d8074, false) + }); + allTemplates.put("minecraft:ender_chest", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ENDER_CHEST).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/ender_chest_front.png"), 0xc82c3e40, false) + }); + allTemplates.put("minecraft:tripwire_hook", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.TRIPWIRE_HOOK).setProperty("direction", 0).setProperty("attached_bit", (byte) 0).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/tripwire_hook.png"), 0x2d8a8171, false) + }); + allTemplates.put("minecraft:tripWire", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.TRIPWIRE).setProperty("attached_bit", (byte) 0).setProperty("disarmed_bit", (byte) 0).setProperty("powered_bit", (byte) 0).setProperty("suspended_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/tripWire.png"), 0x2d818181, false) + }); + allTemplates.put("minecraft:emerald_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.EMERALD_BLOCK).build(), new TexPathBlockIcon("blocks/emerald_block.png"), 0xff51d975, false) + }); + allTemplates.put("minecraft:spruce_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/spruce_stairs.png"), 0xff5a3d0d, false) + }); + allTemplates.put("minecraft:birch_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/birch_stairs.png"), 0xffdabd8d, false) + }); + allTemplates.put("minecraft:jungle_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/jungle_stairs.png"), 0xffBa7d5d, false) + }); + allTemplates.put("minecraft:beacon", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BEACON).build(), new TexPathBlockIcon("blocks/beacon.png"), 0xff74ddd7, false) + }); + allTemplates.put("minecraft:cobblestone_wall", new BlockTemplate[]{ + new BlockTemplate("normal", new Block.Builder(BlockType.COBBLESTONE_WALL).setProperty("wall_block_type", "cobblestone").build(), new TexPathBlockIcon("blocks/cobblestone_wall_normal.png"), 0xff7a7a7a, false), + new BlockTemplate("mossy", new Block.Builder(BlockType.COBBLESTONE_WALL).setProperty("wall_block_type", "mossy_cobblestone").build(), new TexPathBlockIcon("blocks/cobblestone_wall_mossy.png"), 0xff506a50, false) + }); + allTemplates.put("minecraft:flower_pot", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FLOWER_POT).setProperty("update_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/flower_pot.png"), 0x31764133, false) + }); + allTemplates.put("minecraft:carrots", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CARROTS).setProperty("growth", 0).build(), new TexPathBlockIcon("blocks/carrots.png"), 0x0901ab10, false) + }); + allTemplates.put("minecraft:potatoes", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.POTATOES).setProperty("growth", 0).build(), new TexPathBlockIcon("blocks/potatoes.png"), 0x0901ab10, false) + }); + allTemplates.put("minecraft:wooden_button", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.WOODEN_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_button.png"), 0x2878613e, false) + }); + allTemplates.put("minecraft:skull", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SKULL).setProperty("facing_direction", 0).setProperty("no_drop_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/skull.png"), 0x8c8c8c8c, false) + }); + allTemplates.put("minecraft:anvil", new BlockTemplate[]{ + new BlockTemplate("intact", new Block.Builder(BlockType.ANVIL).setProperty("direction", 0).setProperty("damage", "undamaged").build(), new TexPathBlockIcon("blocks/anvil_intact.png"), 0x9f403c3c, false), + new BlockTemplate("slightly_damaged", new Block.Builder(BlockType.ANVIL).setProperty("direction", 0).setProperty("damage", "slightly_damaged").build(), new TexPathBlockIcon("blocks/anvil_slightly_damaged.png"), 0x9f403c3c, false), + new BlockTemplate("very_damaged", new Block.Builder(BlockType.ANVIL).setProperty("direction", 0).setProperty("damage", "very_damaged").build(), new TexPathBlockIcon("blocks/anvil_very_damaged.png"), 0x9f403c3c, false) + }); + allTemplates.put("minecraft:trapped_chest", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.TRAPPED_CHEST).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/chest_front.png"), 0xfe6f5739, false) + }); + allTemplates.put("minecraft:light_weighted_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.LIGHT_WEIGHTED_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/light_weighted_pressure_plate.png"), 0xc8f9ec4e, false) + }); + allTemplates.put("minecraft:heavy_weighted_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.HEAVY_WEIGHTED_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/heavy_weighted_pressure_plate.png"), 0xc8dbdbdb, false) + }); + allTemplates.put("minecraft:unpowered_comparator", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.UNPOWERED_COMPARATOR).setProperty("direction", 0).setProperty("output_lit_bit", (byte) 0).setProperty("output_subtract_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/unpowered_comparator.png"), 0xff9c9695, false) + }); + allTemplates.put("minecraft:powered_comparator", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.POWERED_COMPARATOR).setProperty("direction", 0).setProperty("output_lit_bit", (byte) 0).setProperty("output_subtract_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/powered_comparator.png"), 0xffa59594, false) + }); + allTemplates.put("minecraft:daylight_detector", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DAYLIGHT_DETECTOR).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/daylight_detector.png"), 0xff82745e, false) + }); + allTemplates.put("minecraft:redstone_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.REDSTONE_BLOCK).build(), new TexPathBlockIcon("blocks/redstone_block.png"), 0xffab1b09, false) + }); + allTemplates.put("minecraft:quartz_ore", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.QUARTZ_ORE).build(), new TexPathBlockIcon("blocks/quartz_ore.png"), 0xffd9d1c8, false) + }); + allTemplates.put("minecraft:hopper", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.HOPPER).setProperty("facing_direction", 0).setProperty("toggle_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/hopper.png"), 0xff3e3e3e, false) + }); + allTemplates.put("minecraft:quartz_block", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.QUARTZ_BLOCK).setProperty("chisel_type", "default").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/quartz_block_default.png"), 0xffece9e2, false), + new BlockTemplate("chiseled", new Block.Builder(BlockType.QUARTZ_BLOCK).setProperty("chisel_type", "chiseled").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/quartz_block_chiseled.png"), 0xffe7e4db, false), + new BlockTemplate("lines", new Block.Builder(BlockType.QUARTZ_BLOCK).setProperty("chisel_type", "lines").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/quartz_block_lines.png"), 0xffe8e5dd, false), + new BlockTemplate("default", new Block.Builder(BlockType.QUARTZ_BLOCK).setProperty("chisel_type", "smooth").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/quartz_block_default.png"), 0xffe7e3db, false) + }); + allTemplates.put("minecraft:quartz_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.QUARTZ_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/quartz_stairs.png"), 0xffece9e2, false) + }); + allTemplates.put("minecraft:double_wooden_slab", new BlockTemplate[]{ + new BlockTemplate("oak", new Block.Builder(BlockType.DOUBLE_WOODEN_SLAB).setProperty("wood_type", "oak").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/planks_oak.png"), 0xb4907449, false), + new BlockTemplate("spruce", new Block.Builder(BlockType.DOUBLE_WOODEN_SLAB).setProperty("wood_type", "spruce").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/planks_spruce.png"), 0xff5a3d0d, false), + new BlockTemplate("birch", new Block.Builder(BlockType.DOUBLE_WOODEN_SLAB).setProperty("wood_type", "birch").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/planks_birch.png"), 0xb4dabd8d, false), + new BlockTemplate("jungle", new Block.Builder(BlockType.DOUBLE_WOODEN_SLAB).setProperty("wood_type", "jungle").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/planks_jungle.png"), 0xb4Ba7d5d, false), + new BlockTemplate("acacia", new Block.Builder(BlockType.DOUBLE_WOODEN_SLAB).setProperty("wood_type", "acacia").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/planks_acacia.png"), 0xb4934f39, false), + new BlockTemplate("big_oak", new Block.Builder(BlockType.DOUBLE_WOODEN_SLAB).setProperty("wood_type", "dark_oak").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/planks_big_oak.png"), 0xb4907449, false) + }); + allTemplates.put("minecraft:wooden_slab", new BlockTemplate[]{ + new BlockTemplate("oak", new Block.Builder(BlockType.WOODEN_SLAB).setProperty("wood_type", "oak").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_slab_oak.png"), 0xff907449, false), + new BlockTemplate("spruce", new Block.Builder(BlockType.WOODEN_SLAB).setProperty("wood_type", "spruce").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_slab_spruce.png"), 0xff5a3d0d, false), + new BlockTemplate("birch", new Block.Builder(BlockType.WOODEN_SLAB).setProperty("wood_type", "birch").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_slab_birch.png"), 0xffdabd8d, false), + new BlockTemplate("jungle", new Block.Builder(BlockType.WOODEN_SLAB).setProperty("wood_type", "jungle").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_slab_jungle.png"), 0xffBa7d5d, false), + new BlockTemplate("acacia", new Block.Builder(BlockType.WOODEN_SLAB).setProperty("wood_type", "acacia").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_slab_acacia.png"), 0xff934f39, false), + new BlockTemplate("big_oak", new Block.Builder(BlockType.WOODEN_SLAB).setProperty("wood_type", "dark_oak").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/wooden_slab_big_oak.png"), 0xff907449, false) + }); + allTemplates.put("minecraft:stained_hardened_clay", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_white.png"), 0xff836f64, false), + new BlockTemplate("orange", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_orange.png"), 0xff9d5021, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_magenta.png"), 0xff915369, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_light_blue.png"), 0xff706b87, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_yellow.png"), 0xffb5801f, false), + new BlockTemplate("lime", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_lime.png"), 0xff617030, false), + new BlockTemplate("pink", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_pink.png"), 0xff9c4848, false), + new BlockTemplate("gray", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_gray.png"), 0xff392721, false), + new BlockTemplate("silver", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_silver.png"), 0xff81655b, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_cyan.png"), 0xff565959, false), + new BlockTemplate("purple", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_purple.png"), 0xff744555, false), + new BlockTemplate("blue", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_blue.png"), 0xff463857, false), + new BlockTemplate("brown", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_brown.png"), 0xff492e1f, false), + new BlockTemplate("green", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_green.png"), 0xff484f26, false), + new BlockTemplate("red", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_red.png"), 0xffff382b, false), + new BlockTemplate("black", new Block.Builder(BlockType.STAINED_HARDENED_CLAY).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/hardened_clay_stained_black.png"), 0xff21120d, false) + }); + allTemplates.put("minecraft:stained_glass_pane", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/glass.png"), 0x32141414, false), + new BlockTemplate("orange", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/glass.png"), 0x209d5021, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20915369, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20706b87, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20b5801f, false), + new BlockTemplate("lime", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20617030, false), + new BlockTemplate("pink", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/glass.png"), 0x209c4848, false), + new BlockTemplate("gray", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20392721, false), + new BlockTemplate("silver", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/glass.png"), 0x2081655b, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20565959, false), + new BlockTemplate("purple", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20744555, false), + new BlockTemplate("blue", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20463857, false), + new BlockTemplate("brown", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20492e1f, false), + new BlockTemplate("green", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20484f26, false), + new BlockTemplate("red", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/glass.png"), 0x20ff382b, false), + new BlockTemplate("black", new Block.Builder(BlockType.STAINED_GLASS_PANE).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/glass.png"), 0x2021120d, false) + }); + allTemplates.put("minecraft:leaves2", new BlockTemplate[]{ + new BlockTemplate("acacia", new Block.Builder(BlockType.LEAVES2).setProperty("new_leaf_type", "acacia").setProperty("persistent_bit", (byte) 0).setProperty("update_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/leaves2_acacia.png"), 0xff2e780c, true), + new BlockTemplate("big_oak", new Block.Builder(BlockType.LEAVES2).setProperty("new_leaf_type", "dark_oak").setProperty("persistent_bit", (byte) 0).setProperty("update_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/leaves2_big_oak.png"), 0xff878787, true) + }); + allTemplates.put("minecraft:log2", new BlockTemplate[]{ + new BlockTemplate("acacia", new Block.Builder(BlockType.LOG2).setProperty("new_log_type", "acacia").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/log2_acacia.png"), 0xff934f39, false), + new BlockTemplate("big_oak", new Block.Builder(BlockType.LOG2).setProperty("new_log_type", "dark_oak").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/log2_big_oak.png"), 0xff2d2213, false) + }); + allTemplates.put("minecraft:acacia_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/acacia_stairs.png"), 0xff934f39, false) + }); + allTemplates.put("minecraft:dark_oak_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/dark_oak_stairs.png"), 0xff2d2213, false) + }); + allTemplates.put("minecraft:slime", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SLIME).build(), new TexPathBlockIcon("blocks/slime.png"), 0xc880b672, false) + }); + allTemplates.put("minecraft:iron_trapdoor", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.IRON_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/iron_trapdoor.png"), 0xb4cccccc, false) + }); + allTemplates.put("minecraft:prismarine", new BlockTemplate[]{ + new BlockTemplate("rough", new Block.Builder(BlockType.PRISMARINE).setProperty("prismarine_block_type", "default").build(), new TexPathBlockIcon("blocks/prismarine_rough.png"), 0xff79Ad7e, false), + new BlockTemplate("dark", new Block.Builder(BlockType.PRISMARINE).setProperty("prismarine_block_type", "dark").build(), new TexPathBlockIcon("blocks/prismarine_dark.png"), 0xFF34634e, false), + new BlockTemplate("bricks", new Block.Builder(BlockType.PRISMARINE).setProperty("prismarine_block_type", "bricks").build(), new TexPathBlockIcon("blocks/prismarine_bricks.png"), 0xff59Ad7e, false) + }); + allTemplates.put("minecraft:seaLantern", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SEALANTERN).build(), new TexPathBlockIcon("blocks/seaLantern.png"), 0xffe0eae4, false) + }); + allTemplates.put("minecraft:hay_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.HAY_BLOCK).setProperty("deprecated", 0).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/hay_block.png"), 0xffa3870e, false) + }); + allTemplates.put("minecraft:carpet", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.CARPET).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/carpet_white.png"), 0xffdddddd, false), + new BlockTemplate("orange", new Block.Builder(BlockType.CARPET).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/carpet_orange.png"), 0xffdb7d3e, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.CARPET).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/carpet_magenta.png"), 0xffb350bc, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.CARPET).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/carpet_light_blue.png"), 0xff6a8ac9, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.CARPET).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/carpet_yellow.png"), 0xffb1a627, false), + new BlockTemplate("lime", new Block.Builder(BlockType.CARPET).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/carpet_lime.png"), 0xff41ae38, false), + new BlockTemplate("pink", new Block.Builder(BlockType.CARPET).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/carpet_pink.png"), 0xffd08499, false), + new BlockTemplate("gray", new Block.Builder(BlockType.CARPET).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/carpet_gray.png"), 0xff404040, false), + new BlockTemplate("silver", new Block.Builder(BlockType.CARPET).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/carpet_silver.png"), 0xff9aa1a1, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.CARPET).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/carpet_cyan.png"), 0xff2e6e89, false), + new BlockTemplate("purple", new Block.Builder(BlockType.CARPET).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/carpet_purple.png"), 0xff7e3db5, false), + new BlockTemplate("blue", new Block.Builder(BlockType.CARPET).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/carpet_blue.png"), 0xff2e388d, false), + new BlockTemplate("brown", new Block.Builder(BlockType.CARPET).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/carpet_brown.png"), 0xff4f321f, false), + new BlockTemplate("green", new Block.Builder(BlockType.CARPET).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/carpet_green.png"), 0xff35461b, false), + new BlockTemplate("red", new Block.Builder(BlockType.CARPET).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/carpet_red.png"), 0xff963430, false), + new BlockTemplate("black", new Block.Builder(BlockType.CARPET).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/carpet_black.png"), 0xff191616, false) + }); + allTemplates.put("minecraft:hardened_clay", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.HARDENED_CLAY).build(), new TexPathBlockIcon("blocks/hardened_clay.png"), 0xff5d3828, false) + }); + allTemplates.put("minecraft:coal_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.COAL_BLOCK).build(), new TexPathBlockIcon("blocks/coal_block.png"), 0xff111111, false) + }); + allTemplates.put("minecraft:packed_ice", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PACKED_ICE).build(), new TexPathBlockIcon("blocks/packed_ice.png"), 0xff97b3e4, false) + }); + allTemplates.put("minecraft:double_plant", new BlockTemplate[]{ + new BlockTemplate("sunflower", new Block.Builder(BlockType.DOUBLE_PLANT).setProperty("double_plant_type", "sunflower").setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_plant_sunflower.png"), 0xb4d28219, false), + new BlockTemplate("syringa", new Block.Builder(BlockType.DOUBLE_PLANT).setProperty("double_plant_type", "syringa").setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_plant_syringa.png"), 0xb4dec0e2, false), + new BlockTemplate("grass", new Block.Builder(BlockType.DOUBLE_PLANT).setProperty("double_plant_type", "grass").setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_plant_grass.png"), 0xb4334e2c, false), + new BlockTemplate("fern", new Block.Builder(BlockType.DOUBLE_PLANT).setProperty("double_plant_type", "fern").setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_plant_fern.png"), 0xb43d5d34, false), + new BlockTemplate("rose", new Block.Builder(BlockType.DOUBLE_PLANT).setProperty("double_plant_type", "rose").setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_plant_rose.png"), 0xb4d10609, false), + new BlockTemplate("paeonia", new Block.Builder(BlockType.DOUBLE_PLANT).setProperty("double_plant_type", "paeonia").setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_plant_paeonia.png"), 0xb4d6c1df, false) + }); + allTemplates.put("minecraft:banner", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:daylight_detector_inverted", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DAYLIGHT_DETECTOR_INVERTED).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/daylight_detector_inverted.png"), 0xffd8c9b5, false) + }); + allTemplates.put("minecraft:red_sandstone", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.RED_SANDSTONE).setProperty("sand_stone_type", "default").build(), new TexPathBlockIcon("blocks/red_sandstone_default.png"), 0xffaa561e, false), + new BlockTemplate("chiseled", new Block.Builder(BlockType.RED_SANDSTONE).setProperty("sand_stone_type", "heiroglyphs").build(), new TexPathBlockIcon("blocks/red_sandstone_chiseled.png"), 0xffa8551e, false), + new BlockTemplate("smooth", new Block.Builder(BlockType.RED_SANDSTONE).setProperty("sand_stone_type", "cut").build(), new TexPathBlockIcon("blocks/red_sandstone_smooth.png"), 0xffcc5e16, false) + }); + allTemplates.put("minecraft:red_sandstone_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.RED_SANDSTONE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/red_sandstone_stairs.png"), 0xffaa561e, false) + }); + allTemplates.put("minecraft:double_stone_slab2", new BlockTemplate[]{ + new BlockTemplate("red_sandstone", new Block.Builder(BlockType.DOUBLE_STONE_SLAB2).setProperty("stone_slab_type_2", "red_sandstone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab2_red_sandstone.png"), 0xffaa561e, false), + new BlockTemplate("purpur", new Block.Builder(BlockType.DOUBLE_STONE_SLAB2).setProperty("stone_slab_type_2", "purpur").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/double_stone_slab2_purpur.png"), 0xffa072a0, false) + }); + allTemplates.put("minecraft:stone_slab2", new BlockTemplate[]{ + new BlockTemplate("red_sandstone", new Block.Builder(BlockType.STONE_SLAB2).setProperty("stone_slab_type_2", "red_sandstone").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab2_red_sandstone.png"), 0xffaa561e, false), + new BlockTemplate("purpur", new Block.Builder(BlockType.STONE_SLAB2).setProperty("stone_slab_type_2", "purpur").setProperty("top_slot_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/stone_slab2_purpur.png"), 0xffa072a0, false) + }); + allTemplates.put("minecraft:spruce_fence_gate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_FENCE_GATE).setProperty("direction", 0).setProperty("in_wall_bit", (byte) 0).setProperty("open_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/spruce_fence_gate.png"), 0x8f5a3d0d, false) + }); + allTemplates.put("minecraft:birch_fence_gate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_FENCE_GATE).setProperty("direction", 0).setProperty("in_wall_bit", (byte) 0).setProperty("open_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/birch_fence_gate.png"), 0x8fdabd8d, false) + }); + allTemplates.put("minecraft:jungle_fence_gate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_FENCE_GATE).setProperty("direction", 0).setProperty("in_wall_bit", (byte) 0).setProperty("open_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/jungle_fence_gate.png"), 0x8fBa7d5d, false) + }); + allTemplates.put("minecraft:dark_oak_fence_gate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_FENCE_GATE).setProperty("direction", 0).setProperty("in_wall_bit", (byte) 0).setProperty("open_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/dark_oak_fence_gate.png"), 0x8f2d2213, false) + }); + allTemplates.put("minecraft:acacia_fence_gate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_FENCE_GATE).setProperty("direction", 0).setProperty("in_wall_bit", (byte) 0).setProperty("open_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/acacia_fence_gate.png"), 0x8f934f39, false) + }); + allTemplates.put("minecraft:repeating_command_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 1).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 2).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 3).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 4).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 5).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 1).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 2).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 3).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 4).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 5).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.REPEATING_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false) + }); + allTemplates.put("minecraft:chain_command_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 1).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 2).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 3).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 4).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 5).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 1).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 2).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 3).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 4).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 5).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.CHAIN_COMMAND_BLOCK).setProperty("facing_direction", 0).setProperty("conditional_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/command_block.png"), 0x00000000, false) + }); + allTemplates.put("minecraft:hard_glass_pane", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.HARD_GLASS_PANE).build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false) + }); + allTemplates.put("minecraft:hard_stained_glass_pane", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false), + new BlockTemplate(null, new Block.Builder(BlockType.HARD_STAINED_GLASS_PANE).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/glass_pane_top.png"), 0x00000000, false) + }); + allTemplates.put("minecraft:chemical_heat", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CHEMICAL_HEAT).build(), new TexPathBlockIcon("blocks/fire_0.png"), 0x00000000, false) + }); + allTemplates.put("minecraft:spruce_door", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_DOOR).setProperty("direction", 0).setProperty("door_hinge_bit", (byte) 0).setProperty("open_bit", (byte) 0).setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/spruce_door.png"), 0xff5a3d0d, false) + }); + allTemplates.put("minecraft:birch_door", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_DOOR).setProperty("direction", 0).setProperty("door_hinge_bit", (byte) 0).setProperty("open_bit", (byte) 0).setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/birch_door.png"), 0xffdabd8d, false) + }); + allTemplates.put("minecraft:jungle_door", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_DOOR).setProperty("direction", 0).setProperty("door_hinge_bit", (byte) 0).setProperty("open_bit", (byte) 0).setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/jungle_door.png"), 0xffBa7d5d, false) + }); + allTemplates.put("minecraft:acacia_door", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_DOOR).setProperty("direction", 0).setProperty("door_hinge_bit", (byte) 0).setProperty("open_bit", (byte) 0).setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/acacia_door.png"), 0xff934f39, false) + }); + allTemplates.put("minecraft:dark_oak_door", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_DOOR).setProperty("direction", 0).setProperty("door_hinge_bit", (byte) 0).setProperty("open_bit", (byte) 0).setProperty("upper_block_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/dark_oak_door.png"), 0xff2d2213, false) + }); + allTemplates.put("minecraft:grass_path", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GRASS_PATH).build(), new TexPathBlockIcon("blocks/grass_path.png"), 0x46a0a0a0, false) + }); + allTemplates.put("minecraft:frame", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.FRAME).setProperty("facing_direction", 5).setProperty("item_frame_map_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/frame.png"), 0xa04f3e4f, false) + }); + allTemplates.put("minecraft:chorus_flower", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CHORUS_FLOWER).setProperty("age", 0).build(), new TexPathBlockIcon("blocks/chorus_flower.png"), 0xa0c3b6c8, false) + }); + allTemplates.put("minecraft:purpur_block", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.PURPUR_BLOCK).setProperty("chisel_type", "default").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/purpur_block_default.png"), 0xc095c0ff, false), + new BlockTemplate("chiseled", new Block.Builder(BlockType.PURPUR_BLOCK).setProperty("chisel_type", "chiseled").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/purpur_block_chiseled.png"), 0xc095c0ff, false), + new BlockTemplate("lines", new Block.Builder(BlockType.PURPUR_BLOCK).setProperty("chisel_type", "lines").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/purpur_block_lines.png"), 0xc095c0ff, false), + new BlockTemplate("default", new Block.Builder(BlockType.PURPUR_BLOCK).setProperty("chisel_type", "smooth").setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/purpur_block_default.png"), 0xc095c0ff, false) + }); + allTemplates.put("minecraft:purpur_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PURPUR_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/purpur_stairs.png"), 0xc095c0ff, false) + }); + allTemplates.put("minecraft:shulker_box", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("white", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("orange", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffd030, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffef007f, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5588ff, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff40, false), + new BlockTemplate("lime", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0db60e, false), + new BlockTemplate("pink", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff6076, false), + new BlockTemplate("gray", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff565656, false), + new BlockTemplate("silver", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa6a6a6, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d5656, false), + new BlockTemplate("purple", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff560d56, false), + new BlockTemplate("blue", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d0e56, false), + new BlockTemplate("brown", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff804530, false), + new BlockTemplate("green", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d560e, false), + new BlockTemplate("red", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff2020, false), + new BlockTemplate("black", new Block.Builder(BlockType.SHULKER_BOX).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff000000, false) + }); + allTemplates.put("minecraft:end_bricks", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.END_BRICKS).build(), new TexPathBlockIcon("blocks/end_bricks.png"), 0xffe7f2af, false) + }); + allTemplates.put("minecraft:end_rod", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.END_ROD).setProperty("facing_direction", 0).build(), new TexPathBlockIcon("blocks/end_rod.png"), 0xff6e6e6e, true) + }); + allTemplates.put("minecraft:end_gateway", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.END_GATEWAY).build(), new TexPathBlockIcon("blocks/end_gateway.png"), 0xff171c27, false) + }); + allTemplates.put("minecraft:210", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:211", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:212", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:magma", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.MAGMA).build(), new TexPathBlockIcon("blocks/quartz_block_default.png"), 0xffc45a12, false) + }); + allTemplates.put("minecraft:nether_wart_block", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.NETHER_WART_BLOCK).build(), new TexPathBlockIcon("blocks/quartz_block_default.png"), 0xffbf2030, false) + }); + allTemplates.put("minecraft:red_nether_brick", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.RED_NETHER_BRICK).build(), new TexPathBlockIcon("blocks/quartz_block_default.png"), 0xff7f1020, false) + }); + allTemplates.put("minecraft:bone_block", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.BONE_BLOCK).setProperty("deprecated", 0).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/quartz_block_default.png"), 0xffefe5d2, false) + }); + allTemplates.put("minecraft:purple_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("purple", new Block.Builder(BlockType.PURPLE_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff762d76, false), + new BlockTemplate("purple", new Block.Builder(BlockType.PURPLE_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff762d76, false), + new BlockTemplate("purple", new Block.Builder(BlockType.PURPLE_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff762d76, false), + new BlockTemplate("purple", new Block.Builder(BlockType.PURPLE_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff762d76, false) + }); + allTemplates.put("minecraft:white_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.WHITE_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("white", new Block.Builder(BlockType.WHITE_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("white", new Block.Builder(BlockType.WHITE_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("white", new Block.Builder(BlockType.WHITE_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false) + }); + allTemplates.put("minecraft:orange_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("orange", new Block.Builder(BlockType.ORANGE_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8030, false), + new BlockTemplate("orange", new Block.Builder(BlockType.ORANGE_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8030, false), + new BlockTemplate("orange", new Block.Builder(BlockType.ORANGE_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8030, false), + new BlockTemplate("orange", new Block.Builder(BlockType.ORANGE_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8030, false) + }); + allTemplates.put("minecraft:magenta_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("magenta", new Block.Builder(BlockType.MAGENTA_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff108f, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.MAGENTA_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff108f, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.MAGENTA_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff108f, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.MAGENTA_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff108f, false) + }); + allTemplates.put("minecraft:light_blue_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("light_blue", new Block.Builder(BlockType.LIGHT_BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff75a8ff, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.LIGHT_BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff75a8ff, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.LIGHT_BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff75a8ff, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.LIGHT_BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff75a8ff, false) + }); + allTemplates.put("minecraft:yellow_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("yellow", new Block.Builder(BlockType.YELLOW_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff60, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.YELLOW_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff60, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.YELLOW_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff60, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.YELLOW_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff60, false) + }); + allTemplates.put("minecraft:lime_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("lime", new Block.Builder(BlockType.LIME_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2dd62e, false), + new BlockTemplate("lime", new Block.Builder(BlockType.LIME_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2dd62e, false), + new BlockTemplate("lime", new Block.Builder(BlockType.LIME_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2dd62e, false), + new BlockTemplate("lime", new Block.Builder(BlockType.LIME_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2dd62e, false) + }); + allTemplates.put("minecraft:pink_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("pink", new Block.Builder(BlockType.PINK_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8096, false), + new BlockTemplate("pink", new Block.Builder(BlockType.PINK_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8096, false), + new BlockTemplate("pink", new Block.Builder(BlockType.PINK_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8096, false), + new BlockTemplate("pink", new Block.Builder(BlockType.PINK_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff8096, false) + }); + allTemplates.put("minecraft:gray_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("gray", new Block.Builder(BlockType.GRAY_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff767676, false), + new BlockTemplate("gray", new Block.Builder(BlockType.GRAY_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff767676, false), + new BlockTemplate("gray", new Block.Builder(BlockType.GRAY_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff767676, false), + new BlockTemplate("gray", new Block.Builder(BlockType.GRAY_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff767676, false) + }); + allTemplates.put("minecraft:silver_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("silver", new Block.Builder(BlockType.SILVER_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc6c6c6, false), + new BlockTemplate("silver", new Block.Builder(BlockType.SILVER_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc6c6c6, false), + new BlockTemplate("silver", new Block.Builder(BlockType.SILVER_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc6c6c6, false), + new BlockTemplate("silver", new Block.Builder(BlockType.SILVER_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc6c6c6, false) + }); + allTemplates.put("minecraft:cyan_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("cyan", new Block.Builder(BlockType.CYAN_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d7676, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.CYAN_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d7676, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.CYAN_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d7676, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.CYAN_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d7676, false) + }); + allTemplates.put("minecraft:230", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:blue_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("blue", new Block.Builder(BlockType.BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2e76, false), + new BlockTemplate("blue", new Block.Builder(BlockType.BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2e76, false), + new BlockTemplate("blue", new Block.Builder(BlockType.BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2e76, false), + new BlockTemplate("blue", new Block.Builder(BlockType.BLUE_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2e76, false) + }); + allTemplates.put("minecraft:brown_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("brown", new Block.Builder(BlockType.BROWN_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa06550, false), + new BlockTemplate("brown", new Block.Builder(BlockType.BROWN_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa06550, false), + new BlockTemplate("brown", new Block.Builder(BlockType.BROWN_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa06550, false), + new BlockTemplate("brown", new Block.Builder(BlockType.BROWN_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa06550, false) + }); + allTemplates.put("minecraft:green_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("green", new Block.Builder(BlockType.GREEN_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d762e, false), + new BlockTemplate("green", new Block.Builder(BlockType.GREEN_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d762e, false), + new BlockTemplate("green", new Block.Builder(BlockType.GREEN_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d762e, false), + new BlockTemplate("green", new Block.Builder(BlockType.GREEN_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d762e, false) + }); + allTemplates.put("minecraft:red_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("red", new Block.Builder(BlockType.RED_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff3030, false), + new BlockTemplate("red", new Block.Builder(BlockType.RED_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff3030, false), + new BlockTemplate("red", new Block.Builder(BlockType.RED_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff3030, false), + new BlockTemplate("red", new Block.Builder(BlockType.RED_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff3030, false) + }); + allTemplates.put("minecraft:black_glazed_terracotta", new BlockTemplate[]{ + new BlockTemplate("black", new Block.Builder(BlockType.BLACK_GLAZED_TERRACOTTA).setProperty("facing_direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff050505, false), + new BlockTemplate("black", new Block.Builder(BlockType.BLACK_GLAZED_TERRACOTTA).setProperty("facing_direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff050505, false), + new BlockTemplate("black", new Block.Builder(BlockType.BLACK_GLAZED_TERRACOTTA).setProperty("facing_direction", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff050505, false), + new BlockTemplate("black", new Block.Builder(BlockType.BLACK_GLAZED_TERRACOTTA).setProperty("facing_direction", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff050505, false) + }); + allTemplates.put("minecraft:concrete", new BlockTemplate[]{ + new BlockTemplate("orange", new Block.Builder(BlockType.CONCRETE).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("orange", new Block.Builder(BlockType.CONCRETE).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffd030, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.CONCRETE).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffef007f, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.CONCRETE).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5588ff, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.CONCRETE).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff40, false), + new BlockTemplate("lime", new Block.Builder(BlockType.CONCRETE).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0db60e, false), + new BlockTemplate("pink", new Block.Builder(BlockType.CONCRETE).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff6076, false), + new BlockTemplate("gray", new Block.Builder(BlockType.CONCRETE).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff565656, false), + new BlockTemplate("silver", new Block.Builder(BlockType.CONCRETE).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa6a6a6, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.CONCRETE).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d5656, false), + new BlockTemplate("purple", new Block.Builder(BlockType.CONCRETE).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff560d56, false), + new BlockTemplate("blue", new Block.Builder(BlockType.CONCRETE).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d0e56, false), + new BlockTemplate("brown", new Block.Builder(BlockType.CONCRETE).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff804530, false), + new BlockTemplate("green", new Block.Builder(BlockType.CONCRETE).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d560e, false), + new BlockTemplate("red", new Block.Builder(BlockType.CONCRETE).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff2020, false), + new BlockTemplate("black", new Block.Builder(BlockType.CONCRETE).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff000000, false) + }); + allTemplates.put("minecraft:concretePowder", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("orange", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffd030, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffef007f, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5588ff, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff40, false), + new BlockTemplate("lime", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0db60e, false), + new BlockTemplate("pink", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff6076, false), + new BlockTemplate("gray", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff565656, false), + new BlockTemplate("silver", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa6a6a6, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d5656, false), + new BlockTemplate("purple", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff560d56, false), + new BlockTemplate("blue", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d0e56, false), + new BlockTemplate("brown", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff804530, false), + new BlockTemplate("green", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d560e, false), + new BlockTemplate("brown", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff2020, false), + new BlockTemplate("black", new Block.Builder(BlockType.CONCRETEPOWDER).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff000000, false) + }); + allTemplates.put("minecraft:chemistry_table", new BlockTemplate[]{ + new BlockTemplate("orange", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "compound_creator").setProperty("direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("orange", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "compound_creator").setProperty("direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffd030, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "compound_creator").setProperty("direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffef007f, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "compound_creator").setProperty("direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5588ff, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "material_reducer").setProperty("direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff40, false), + new BlockTemplate("lime", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "material_reducer").setProperty("direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0db60e, false), + new BlockTemplate("pink", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "material_reducer").setProperty("direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff6076, false), + new BlockTemplate("gray", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "material_reducer").setProperty("direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff565656, false), + new BlockTemplate("silver", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "element_constructor").setProperty("direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffa6a6a6, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "element_constructor").setProperty("direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d5656, false), + new BlockTemplate("purple", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "element_constructor").setProperty("direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff560d56, false), + new BlockTemplate("blue", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "element_constructor").setProperty("direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d0e56, false), + new BlockTemplate("brown", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "lab_table").setProperty("direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff804530, false), + new BlockTemplate("green", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "lab_table").setProperty("direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0d560e, false), + new BlockTemplate("brown", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "lab_table").setProperty("direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff2020, false), + new BlockTemplate("black", new Block.Builder(BlockType.CHEMISTRY_TABLE).setProperty("chemistry_table_type", "lab_table").setProperty("direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff000000, false) + }); + allTemplates.put("minecraft:underwater_torch", new BlockTemplate[]{ + new BlockTemplate("orange", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "unknown").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffffff, false), + new BlockTemplate("orange", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "west").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffd030, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "east").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffef007f, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "north").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5588ff, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "south").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffffff40, false), + new BlockTemplate("lime", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "top").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff0db60e, false), + new BlockTemplate("pink", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "unknown").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffff6076, false), + new BlockTemplate("gray", new Block.Builder(BlockType.UNDERWATER_TORCH).setProperty("torch_facing_direction", "unknown").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff565656, false) + }); + allTemplates.put("minecraft:chorus_plant", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CHORUS_PLANT).build(), new TexPathBlockIcon("blocks/chorus_plant.png"), 0xaa3d6e86, false) + }); + allTemplates.put("minecraft:stained_glass", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/stained_glass_white.png"), 0x50836f64, false), + new BlockTemplate("orange", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/stained_glass_orange.png"), 0x509d5021, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/stained_glass_magenta.png"), 0x50915369, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/stained_glass_light_blue.png"), 0x50706b87, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/stained_glass_yellow.png"), 0x50b5801f, false), + new BlockTemplate("lime", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/stained_glass_lime.png"), 0x50617030, false), + new BlockTemplate("pink", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/stained_glass_pink.png"), 0x509c4848, false), + new BlockTemplate("gray", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/stained_glass_gray.png"), 0x50392721, false), + new BlockTemplate("silver", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/stained_glass_silver.png"), 0x5081655b, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/stained_glass_cyan.png"), 0x50565959, false), + new BlockTemplate("purple", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/stained_glass_purple.png"), 0x50744555, false), + new BlockTemplate("blue", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/stained_glass_blue.png"), 0x50463857, false), + new BlockTemplate("brown", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/stained_glass_brown.png"), 0x50492e1f, false), + new BlockTemplate("green", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/stained_glass_green.png"), 0x50484f26, false), + new BlockTemplate("red", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/stained_glass_red.png"), 0x50ff382b, false), + new BlockTemplate("black", new Block.Builder(BlockType.STAINED_GLASS).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/stained_glass_black.png"), 0x5021120d, false) + }); + allTemplates.put("minecraft:242", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:podzol", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PODZOL).build(), new TexPathBlockIcon("blocks/podzol.png"), 0xff533a1b, true) + }); + allTemplates.put("minecraft:beetroot", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BEETROOT).setProperty("growth", 0).build(), new TexPathBlockIcon("blocks/beetroot.png"), 0x0901ab10, false) + }); + allTemplates.put("minecraft:stonecutter", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STONECUTTER).build(), new TexPathBlockIcon("blocks/stonecutter.png"), 0xff515151, false) + }); + allTemplates.put("minecraft:glowingobsidian", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.GLOWINGOBSIDIAN).build(), new TexPathBlockIcon("blocks/glowingobsidian.png"), 0xff17060a, false) + }); + allTemplates.put("minecraft:netherreactor", new BlockTemplate[]{ + new BlockTemplate("default", new Block.Builder(BlockType.NETHERREACTOR).build(), new TexPathBlockIcon("blocks/netherreactor_default.png"), 0xffd2d200, false), + new BlockTemplate("active", new Block.Builder(BlockType.NETHERREACTOR).build(), new TexPathBlockIcon("blocks/netherreactor_active.png"), 0xff3d6e86, false), + new BlockTemplate("cooled", new Block.Builder(BlockType.NETHERREACTOR).build(), new TexPathBlockIcon("blocks/netherreactor_cooled.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:info_update", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.INFO_UPDATE).build(), new TexPathBlockIcon("blocks/info_update.png"), 0xff2f3218, false) + }); + allTemplates.put("minecraft:info_update2", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.INFO_UPDATE2).build(), new TexPathBlockIcon("blocks/info_update2.png"), 0xff2f3218, false) + }); + allTemplates.put("minecraft:movingBlock", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.MOVINGBLOCK).build(), new TexPathBlockIcon("blocks/movingBlock.png"), 0, false) + }); + allTemplates.put("minecraft:observer", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 0).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 1).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 2).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 3).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 4).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 5).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 0).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 0).setProperty("powered_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 0).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 1).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 2).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 3).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 4).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 5).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 0).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.OBSERVER).setProperty("facing_direction", 0).setProperty("powered_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:structure_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "data").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "save").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "load").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "corner").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "invalid").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "export").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "data").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRUCTURE_BLOCK).setProperty("structure_block_type", "data").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:hard_glass", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.HARD_GLASS).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:hard_stained_glass", new BlockTemplate[]{ + new BlockTemplate("white", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "white").build(), new TexPathBlockIcon("blocks/stained_glass_white.png"), 0x50836f64, false), + new BlockTemplate("orange", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "orange").build(), new TexPathBlockIcon("blocks/stained_glass_orange.png"), 0x509d5021, false), + new BlockTemplate("magenta", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "magenta").build(), new TexPathBlockIcon("blocks/stained_glass_magenta.png"), 0x50915369, false), + new BlockTemplate("light_blue", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "light_blue").build(), new TexPathBlockIcon("blocks/stained_glass_light_blue.png"), 0x50706b87, false), + new BlockTemplate("yellow", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "yellow").build(), new TexPathBlockIcon("blocks/stained_glass_yellow.png"), 0x50b5801f, false), + new BlockTemplate("lime", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "lime").build(), new TexPathBlockIcon("blocks/stained_glass_lime.png"), 0x50617030, false), + new BlockTemplate("pink", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "pink").build(), new TexPathBlockIcon("blocks/stained_glass_pink.png"), 0x509c4848, false), + new BlockTemplate("gray", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "gray").build(), new TexPathBlockIcon("blocks/stained_glass_gray.png"), 0x50392721, false), + new BlockTemplate("silver", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "silver").build(), new TexPathBlockIcon("blocks/stained_glass_silver.png"), 0x5081655b, false), + new BlockTemplate("cyan", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "cyan").build(), new TexPathBlockIcon("blocks/stained_glass_cyan.png"), 0x50565959, false), + new BlockTemplate("purple", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "purple").build(), new TexPathBlockIcon("blocks/stained_glass_purple.png"), 0x50744555, false), + new BlockTemplate("blue", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "blue").build(), new TexPathBlockIcon("blocks/stained_glass_blue.png"), 0x50463857, false), + new BlockTemplate("brown", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "brown").build(), new TexPathBlockIcon("blocks/stained_glass_brown.png"), 0x50492e1f, false), + new BlockTemplate("green", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "green").build(), new TexPathBlockIcon("blocks/stained_glass_green.png"), 0x50484f26, false), + new BlockTemplate("red", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "red").build(), new TexPathBlockIcon("blocks/stained_glass_red.png"), 0x50ff382b, false), + new BlockTemplate("black", new Block.Builder(BlockType.HARD_STAINED_GLASS).setProperty("color", "black").build(), new TexPathBlockIcon("blocks/stained_glass_black.png"), 0x5021120d, false) + }); + allTemplates.put("minecraft:reserved6", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.RESERVED6).build(), new TexPathBlockIcon("blocks/reserved6.png"), 0xff19171a, false) + }); + allTemplates.put("minecraft:256", new BlockTemplate[]{ + + }); + allTemplates.put("minecraft:prismarine_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 2).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 3).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 2).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_STAIRS).setProperty("weirdo_direction", 3).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xA9498d6e, false) + }); + allTemplates.put("minecraft:dark_prismarine_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 2).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 3).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 2).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_PRISMARINE_STAIRS).setProperty("weirdo_direction", 3).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04635e, false) + }); + allTemplates.put("minecraft:prismarine_bricks_stairs", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 2).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 3).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 2).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false), + new BlockTemplate(null, new Block.Builder(BlockType.PRISMARINE_BRICKS_STAIRS).setProperty("weirdo_direction", 3).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff097d6e, false) + }); + allTemplates.put("minecraft:stripped_spruce_log", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_SPRUCE_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_SPRUCE_LOG).setProperty("pillar_axis", "x").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_SPRUCE_LOG).setProperty("pillar_axis", "z").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_SPRUCE_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false) + }); + allTemplates.put("minecraft:stripped_birch_log", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_BIRCH_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_BIRCH_LOG).setProperty("pillar_axis", "x").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_BIRCH_LOG).setProperty("pillar_axis", "z").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_BIRCH_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false) + }); + allTemplates.put("minecraft:stripped_jungle_log", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_JUNGLE_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_JUNGLE_LOG).setProperty("pillar_axis", "x").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_JUNGLE_LOG).setProperty("pillar_axis", "z").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_JUNGLE_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false) + }); + allTemplates.put("minecraft:stripped_acacia_log", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_ACACIA_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_ACACIA_LOG).setProperty("pillar_axis", "x").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_ACACIA_LOG).setProperty("pillar_axis", "z").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_ACACIA_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false) + }); + allTemplates.put("minecraft:stripped_dark_oak_log", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_DARK_OAK_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_DARK_OAK_LOG).setProperty("pillar_axis", "x").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_DARK_OAK_LOG).setProperty("pillar_axis", "z").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_DARK_OAK_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false) + }); + allTemplates.put("minecraft:stripped_oak_log", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_OAK_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff9a7d4d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_OAK_LOG).setProperty("pillar_axis", "x").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff9a7d4d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_OAK_LOG).setProperty("pillar_axis", "z").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff9a7d4d, false), + new BlockTemplate(null, new Block.Builder(BlockType.STRIPPED_OAK_LOG).setProperty("pillar_axis", "y").build(), new TexPathBlockIcon("blocks/observer.png"), 0xff9a7d4d, false) + }); + allTemplates.put("minecraft:blue_ice", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BLUE_ICE).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff7dbeF6, false) + }); + allTemplates.put("minecraft:seagrass", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SEAGRASS).setProperty("sea_grass_type", "default").build(), new TexPathBlockIcon("blocks/observer.png"), 0x4e787878, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEAGRASS).setProperty("sea_grass_type", "double_top").build(), new TexPathBlockIcon("blocks/observer.png"), 0x4e787878, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEAGRASS).setProperty("sea_grass_type", "double_bot").build(), new TexPathBlockIcon("blocks/observer.png"), 0x4e787878, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEAGRASS).setProperty("sea_grass_type", "default").build(), new TexPathBlockIcon("blocks/observer.png"), 0x4e787878, false) + }); + allTemplates.put("minecraft:coral", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "pink").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "purple").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "red").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "yellow").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "pink").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "purple").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "red").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "yellow").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:coral_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "pink").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "purple").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "red").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "yellow").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "pink").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "purple").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "red").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "yellow").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_BLOCK).setProperty("coral_color", "blue").setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:coral_fan", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "pink").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "yellow").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "pink").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "purple").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "red").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "yellow").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:coral_fan_dead", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "pink").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "purple").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "red").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "yellow").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "pink").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "purple").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "red").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "yellow").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_DEAD).setProperty("coral_color", "blue").setProperty("coral_fan_direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xFFC8C8C8, false) + }); + allTemplates.put("minecraft:coral_fan_hang", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:coral_fan_hang2", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG2).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:coral_fan_hang3", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 0).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 1).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 2).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 0).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false), + new BlockTemplate(null, new Block.Builder(BlockType.CORAL_FAN_HANG3).setProperty("coral_hang_type_bit", (byte) 1).setProperty("coral_direction", 3).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff3d6e86, false) + }); + allTemplates.put("minecraft:kelp", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 6).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 7).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 8).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 9).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 10).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 11).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 12).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 13).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 14).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false), + new BlockTemplate(null, new Block.Builder(BlockType.KELP).setProperty("kelp_age", 15).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff04833e, false) + }); + allTemplates.put("minecraft:dried_kelp_block", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DRIED_KELP_BLOCK).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff044b4b, false) + }); + allTemplates.put("minecraft:acacia_button", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0x5f934f39, false) + }); + allTemplates.put("minecraft:birch_button", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false) + }); + allTemplates.put("minecraft:dark_oak_button", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false) + }); + allTemplates.put("minecraft:jungle_button", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false) + }); + allTemplates.put("minecraft:spruce_button", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 1).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 2).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 3).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 4).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 5).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_BUTTON).setProperty("facing_direction", 0).setProperty("button_pressed_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false) + }); + allTemplates.put("minecraft:acacia_trapdoor", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false) + }); + allTemplates.put("minecraft:birch_trapdoor", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false) + }); + allTemplates.put("minecraft:dark_oak_trapdoor", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false) + }); + allTemplates.put("minecraft:jungle_trapdoor", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false) + }); + allTemplates.put("minecraft:spruce_trapdoor", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 0).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 0).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 1).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 2).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_TRAPDOOR).setProperty("direction", 3).setProperty("open_bit", (byte) 1).setProperty("upside_down_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false) + }); + allTemplates.put("minecraft:acacia_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 6).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 7).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 8).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 9).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 10).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 11).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 12).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 13).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 14).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false), + new BlockTemplate(null, new Block.Builder(BlockType.ACACIA_PRESSURE_PLATE).setProperty("redstone_signal", 15).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff934f39, false) + }); + allTemplates.put("minecraft:birch_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 6).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 7).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 8).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 9).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 10).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 11).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 12).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 13).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 14).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false), + new BlockTemplate(null, new Block.Builder(BlockType.BIRCH_PRESSURE_PLATE).setProperty("redstone_signal", 15).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffdabd8d, false) + }); + allTemplates.put("minecraft:dark_oak_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 6).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 7).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 8).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 9).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 10).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 11).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 12).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 13).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 14).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false), + new BlockTemplate(null, new Block.Builder(BlockType.DARK_OAK_PRESSURE_PLATE).setProperty("redstone_signal", 15).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff2d2213, false) + }); + allTemplates.put("minecraft:jungle_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 6).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 7).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 8).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 9).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 10).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 11).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 12).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 13).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 14).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false), + new BlockTemplate(null, new Block.Builder(BlockType.JUNGLE_PRESSURE_PLATE).setProperty("redstone_signal", 15).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffBa7d5d, false) + }); + allTemplates.put("minecraft:spruce_pressure_plate", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 4).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 5).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 6).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 7).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 8).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 9).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 10).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 11).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 12).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 13).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 14).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false), + new BlockTemplate(null, new Block.Builder(BlockType.SPRUCE_PRESSURE_PLATE).setProperty("redstone_signal", 15).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff5a3d0d, false) + }); + allTemplates.put("minecraft:carved_pumpkin", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.CARVED_PUMPKIN).setProperty("direction", 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc07615, false), + new BlockTemplate(null, new Block.Builder(BlockType.CARVED_PUMPKIN).setProperty("direction", 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc07615, false), + new BlockTemplate(null, new Block.Builder(BlockType.CARVED_PUMPKIN).setProperty("direction", 2).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc07615, false), + new BlockTemplate(null, new Block.Builder(BlockType.CARVED_PUMPKIN).setProperty("direction", 3).build(), new TexPathBlockIcon("blocks/observer.png"), 0xffc07615, false) + }); + allTemplates.put("minecraft:sea_pickle", new BlockTemplate[]{ + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 0).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 1).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 2).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 3).setProperty("dead_bit", (byte) 0).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 0).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 1).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 2).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false), + new BlockTemplate(null, new Block.Builder(BlockType.SEA_PICKLE).setProperty("cluster_count", 3).setProperty("dead_bit", (byte) 1).build(), new TexPathBlockIcon("blocks/observer.png"), 0xff10C38e, false) + }); + } + + public static BlockTemplate[] getOfType(@NonNull String name) { + if (!name.contains(":")) name = "minecraft:" + name; + return allTemplates.get(name); + } + + @NonNull + public static BlockTemplate getBest(@NonNull Block block) { + var type = block.getType(); + if (type == null) return getUnknownBlockTemplate(); + List candidates = Arrays.asList(Objects.requireNonNull(getOfType(type.getName()))); + for (int i = 0, limit = block.getType().getKnownProperties().length; i < limit; i++) { + List newCandidates = new ArrayList<>(); + for (var template : candidates) { + if (Objects.equals(template.getBlock().getKnownProperties()[i], block.getKnownProperties()[i])) + newCandidates.add(template); + } + switch (newCandidates.size()) { + case 0: // give up filtering based on this property + continue; + case 1: // no longer an option + return newCandidates.get(0); + default: // less candidates + candidates = newCandidates; + } + } + return candidates.size() > 0 ? candidates.get(0) : getUnknownBlockTemplate(); + } + + public static Stream getAll() { + var stream = Arrays.stream(new BlockTemplate[0]); + for (var templates : allTemplates.values()) + stream = Streams.concat(stream, Arrays.stream(templates)); + return stream; + } + + @NonNull + public static BlockTemplate getAirTemplate() { + return getOfType("minecraft:air")[0]; + } + + @NonNull + public static BlockTemplate getUnknownBlockTemplate() { + return unknownBlockTemplate; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockType.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockType.java new file mode 100644 index 00000000..0ef4e750 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockType.java @@ -0,0 +1,327 @@ +package com.mithrilmania.blocktopograph.block; + +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.block.blockproperty.BlockProperty; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public enum BlockType implements Serializable { + AIR("minecraft:air", new BlockProperty[]{}), + STONE("minecraft:stone", new BlockProperty[]{BlockProperty.STONE_TYPE}), + GRASS("minecraft:grass", new BlockProperty[]{}), + DIRT("minecraft:dirt", new BlockProperty[]{BlockProperty.DIRT_TYPE}), + COBBLESTONE("minecraft:cobblestone", new BlockProperty[]{}), + PLANKS("minecraft:planks", new BlockProperty[]{BlockProperty.WOOD_TYPE}), + SAPLING("minecraft:sapling", new BlockProperty[]{BlockProperty.SAPLING_TYPE, BlockProperty.AGE_BIT}), + BEDROCK("minecraft:bedrock", new BlockProperty[]{BlockProperty.INFINIBURN_BIT}), + FLOWING_WATER("minecraft:flowing_water", new BlockProperty[]{BlockProperty.LIQUID_DEPTH}), + WATER("minecraft:water", new BlockProperty[]{BlockProperty.LIQUID_DEPTH}), + FLOWING_LAVA("minecraft:flowing_lava", new BlockProperty[]{BlockProperty.LIQUID_DEPTH}), + LAVA("minecraft:lava", new BlockProperty[]{BlockProperty.LIQUID_DEPTH}), + SAND("minecraft:sand", new BlockProperty[]{BlockProperty.SAND_TYPE}), + GRAVEL("minecraft:gravel", new BlockProperty[]{}), + GOLD_ORE("minecraft:gold_ore", new BlockProperty[]{}), + IRON_ORE("minecraft:iron_ore", new BlockProperty[]{}), + COAL_ORE("minecraft:coal_ore", new BlockProperty[]{}), + LOG("minecraft:log", new BlockProperty[]{BlockProperty.OLD_LOG_TYPE, BlockProperty.PILLAR_AXIS}), + LEAVES("minecraft:leaves", new BlockProperty[]{BlockProperty.OLD_LEAF_TYPE, BlockProperty.PERSISTENT_BIT, BlockProperty.UPDATE_BIT}), + SPONGE("minecraft:sponge", new BlockProperty[]{BlockProperty.SPONGE_TYPE}), + GLASS("minecraft:glass", new BlockProperty[]{}), + LAPIS_ORE("minecraft:lapis_ore", new BlockProperty[]{}), + LAPIS_BLOCK("minecraft:lapis_block", new BlockProperty[]{}), + DISPENSER("minecraft:dispenser", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.TRIGGERED_BIT}), + SANDSTONE("minecraft:sandstone", new BlockProperty[]{BlockProperty.SAND_STONE_TYPE}), + NOTEBLOCK("minecraft:noteblock", new BlockProperty[]{}), + BED("minecraft:bed", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.HEAD_PIECE_BIT, BlockProperty.OCCUPIED_BIT}), + GOLDEN_RAIL("minecraft:golden_rail", new BlockProperty[]{BlockProperty.RAIL_DIRECTION, BlockProperty.RAIL_DATA_BIT}), + DETECTOR_RAIL("minecraft:detector_rail", new BlockProperty[]{BlockProperty.RAIL_DIRECTION, BlockProperty.RAIL_DATA_BIT}), + STICKY_PISTON("minecraft:sticky_piston", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + WEB("minecraft:web", new BlockProperty[]{}), + TALLGRASS("minecraft:tallgrass", new BlockProperty[]{BlockProperty.TALL_GRASS_TYPE}), + DEADBUSH("minecraft:deadbush", new BlockProperty[]{}), + PISTON("minecraft:piston", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + PISTONARMCOLLISION("minecraft:pistonArmCollision", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + WOOL("minecraft:wool", new BlockProperty[]{BlockProperty.COLOR}), + ELEMENT_0("minecraft:element_0", new BlockProperty[]{}), + YELLOW_FLOWER("minecraft:yellow_flower", new BlockProperty[]{}), + RED_FLOWER("minecraft:red_flower", new BlockProperty[]{BlockProperty.FLOWER_TYPE}), + BROWN_MUSHROOM("minecraft:brown_mushroom", new BlockProperty[]{}), + RED_MUSHROOM("minecraft:red_mushroom", new BlockProperty[]{}), + GOLD_BLOCK("minecraft:gold_block", new BlockProperty[]{}), + IRON_BLOCK("minecraft:iron_block", new BlockProperty[]{}), + DOUBLE_STONE_SLAB("minecraft:double_stone_slab", new BlockProperty[]{BlockProperty.STONE_SLAB_TYPE, BlockProperty.TOP_SLOT_BIT}), + STONE_SLAB("minecraft:stone_slab", new BlockProperty[]{BlockProperty.STONE_SLAB_TYPE, BlockProperty.TOP_SLOT_BIT}), + BRICK_BLOCK("minecraft:brick_block", new BlockProperty[]{}), + TNT("minecraft:tnt", new BlockProperty[]{BlockProperty.ALLOW_UNDERWATER_BIT, BlockProperty.EXPLODE_BIT}), + BOOKSHELF("minecraft:bookshelf", new BlockProperty[]{}), + MOSSY_COBBLESTONE("minecraft:mossy_cobblestone", new BlockProperty[]{}), + OBSIDIAN("minecraft:obsidian", new BlockProperty[]{}), + TORCH("minecraft:torch", new BlockProperty[]{BlockProperty.TORCH_FACING_DIRECTION}), + FIRE("minecraft:fire", new BlockProperty[]{BlockProperty.AGE}), + MOB_SPAWNER("minecraft:mob_spawner", new BlockProperty[]{}), + OAK_STAIRS("minecraft:oak_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + CHEST("minecraft:chest", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + REDSTONE_WIRE("minecraft:redstone_wire", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + DIAMOND_ORE("minecraft:diamond_ore", new BlockProperty[]{}), + DIAMOND_BLOCK("minecraft:diamond_block", new BlockProperty[]{}), + CRAFTING_TABLE("minecraft:crafting_table", new BlockProperty[]{}), + WHEAT("minecraft:wheat", new BlockProperty[]{BlockProperty.GROWTH}), + FARMLAND("minecraft:farmland", new BlockProperty[]{BlockProperty.MOISTURIZED_AMOUNT}), + FURNACE("minecraft:furnace", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + LIT_FURNACE("minecraft:lit_furnace", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + STANDING_SIGN("minecraft:standing_sign", new BlockProperty[]{BlockProperty.GROUND_SIGN_DIRECTION}), + WOODEN_DOOR("minecraft:wooden_door", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DOOR_HINGE_BIT, BlockProperty.OPEN_BIT, BlockProperty.UPPER_BLOCK_BIT}), + LADDER("minecraft:ladder", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + RAIL("minecraft:rail", new BlockProperty[]{BlockProperty.RAIL_DIRECTION}), + STONE_STAIRS("minecraft:stone_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + WALL_SIGN("minecraft:wall_sign", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + LEVER("minecraft:lever", new BlockProperty[]{BlockProperty.LEVER_DIRECTION, BlockProperty.OPEN_BIT}), + STONE_PRESSURE_PLATE("minecraft:stone_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + IRON_DOOR("minecraft:iron_door", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DOOR_HINGE_BIT, BlockProperty.OPEN_BIT, BlockProperty.UPPER_BLOCK_BIT}), + WOODEN_PRESSURE_PLATE("minecraft:wooden_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + REDSTONE_ORE("minecraft:redstone_ore", new BlockProperty[]{}), + LIT_REDSTONE_ORE("minecraft:lit_redstone_ore", new BlockProperty[]{}), + UNLIT_REDSTONE_TORCH("minecraft:unlit_redstone_torch", new BlockProperty[]{}), + REDSTONE_TORCH("minecraft:redstone_torch", new BlockProperty[]{BlockProperty.TORCH_FACING_DIRECTION}), + STONE_BUTTON("minecraft:stone_button", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.BUTTON_PRESSED_BIT}), + SNOW_LAYER("minecraft:snow_layer", new BlockProperty[]{BlockProperty.COVERED_BIT, BlockProperty.HEIGHT}), + ICE("minecraft:ice", new BlockProperty[]{}), + SNOW("minecraft:snow", new BlockProperty[]{}), + CACTUS("minecraft:cactus", new BlockProperty[]{BlockProperty.AGE}), + CLAY("minecraft:clay", new BlockProperty[]{}), + REEDS("minecraft:reeds", new BlockProperty[]{BlockProperty.AGE}), + JUKEBOX("minecraft:jukebox", new BlockProperty[]{}), + FENCE("minecraft:fence", new BlockProperty[]{BlockProperty.WOOD_TYPE}), + PUMPKIN("minecraft:pumpkin", new BlockProperty[]{BlockProperty.DIRECTION}), + NETHERRACK("minecraft:netherrack", new BlockProperty[]{}), + SOUL_SAND("minecraft:soul_sand", new BlockProperty[]{}), + GLOWSTONE("minecraft:glowstone", new BlockProperty[]{}), + PORTAL("minecraft:portal", new BlockProperty[]{BlockProperty.PORTAL_AXIS}), + LIT_PUMPKIN("minecraft:lit_pumpkin", new BlockProperty[]{BlockProperty.DIRECTION}), + CAKE("minecraft:cake", new BlockProperty[]{BlockProperty.BITE_COUNTER}), + UNPOWERED_REPEATER("minecraft:unpowered_repeater", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.REPEATER_DELAY}), + POWERED_REPEATER("minecraft:powered_repeater", new BlockProperty[]{}), + INVISIBLEBEDROCK("minecraft:invisibleBedrock", new BlockProperty[]{}), + TRAPDOOR("minecraft:trapdoor", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OPEN_BIT, BlockProperty.UPSIDE_DOWN_BIT}), + MONSTER_EGG("minecraft:monster_egg", new BlockProperty[]{BlockProperty.MONSTER_EGG_STONE_TYPE}), + STONEBRICK("minecraft:stonebrick", new BlockProperty[]{BlockProperty.STONE_BRICK_TYPE}), + BROWN_MUSHROOM_BLOCK("minecraft:brown_mushroom_block", new BlockProperty[]{BlockProperty.HUGE_MUSHROOM_BITS}), + RED_MUSHROOM_BLOCK("minecraft:red_mushroom_block", new BlockProperty[]{BlockProperty.HUGE_MUSHROOM_BITS}), + IRON_BARS("minecraft:iron_bars", new BlockProperty[]{}), + GLASS_PANE("minecraft:glass_pane", new BlockProperty[]{}), + MELON_BLOCK("minecraft:melon_block", new BlockProperty[]{}), + PUMPKIN_STEM("minecraft:pumpkin_stem", new BlockProperty[]{BlockProperty.GROWTH}), + MELON_STEM("minecraft:melon_stem", new BlockProperty[]{BlockProperty.GROWTH}), + VINE("minecraft:vine", new BlockProperty[]{BlockProperty.VINE_DIRECTION_BITS}), + FENCE_GATE("minecraft:fence_gate", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.IN_WALL_BIT, BlockProperty.OPEN_BIT}), + BRICK_STAIRS("minecraft:brick_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + STONE_BRICK_STAIRS("minecraft:stone_brick_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + MYCELIUM("minecraft:mycelium", new BlockProperty[]{}), + WATERLILY("minecraft:waterlily", new BlockProperty[]{}), + NETHER_BRICK("minecraft:nether_brick", new BlockProperty[]{}), + NETHER_BRICK_FENCE("minecraft:nether_brick_fence", new BlockProperty[]{}), + NETHER_BRICK_STAIRS("minecraft:nether_brick_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + NETHER_WART("minecraft:nether_wart", new BlockProperty[]{BlockProperty.AGE}), + ENCHANTING_TABLE("minecraft:enchanting_table", new BlockProperty[]{}), + BREWING_STAND("minecraft:brewing_stand", new BlockProperty[]{BlockProperty.BREWING_STAND_SLOT_A_BIT, BlockProperty.BREWING_STAND_SLOT_B_BIT, BlockProperty.BREWING_STAND_SLOT_C_BIT}), + CAULDRON("minecraft:cauldron", new BlockProperty[]{BlockProperty.CAULDRON_LIQUID, BlockProperty.FILL_LEVEL}), + END_PORTAL("minecraft:end_portal", new BlockProperty[]{}), + END_PORTAL_FRAME("minecraft:end_portal_frame", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.END_PORTAL_EYE_BIT}), + END_STONE("minecraft:end_stone", new BlockProperty[]{}), + DRAGON_EGG("minecraft:dragon_egg", new BlockProperty[]{}), + REDSTONE_LAMP("minecraft:redstone_lamp", new BlockProperty[]{}), + LIT_REDSTONE_LAMP("minecraft:lit_redstone_lamp", new BlockProperty[]{}), + DROPPER("minecraft:dropper", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.TRIGGERED_BIT}), + ACTIVATOR_RAIL("minecraft:activator_rail", new BlockProperty[]{BlockProperty.RAIL_DIRECTION, BlockProperty.RAIL_DATA_BIT}), + COCOA("minecraft:cocoa", new BlockProperty[]{}), + SANDSTONE_STAIRS("minecraft:sandstone_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + EMERALD_ORE("minecraft:emerald_ore", new BlockProperty[]{}), + ENDER_CHEST("minecraft:ender_chest", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + TRIPWIRE_HOOK("minecraft:tripwire_hook", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.ATTACHED_BIT, BlockProperty.POWERED_BIT}), + TRIPWIRE("minecraft:tripWire", new BlockProperty[]{BlockProperty.ATTACHED_BIT, BlockProperty.DISARMED_BIT, BlockProperty.POWERED_BIT, BlockProperty.SUSPENDED_BIT}), + EMERALD_BLOCK("minecraft:emerald_block", new BlockProperty[]{}), + SPRUCE_STAIRS("minecraft:spruce_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + BIRCH_STAIRS("minecraft:birch_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + JUNGLE_STAIRS("minecraft:jungle_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + BEACON("minecraft:beacon", new BlockProperty[]{}), + COBBLESTONE_WALL("minecraft:cobblestone_wall", new BlockProperty[]{BlockProperty.WALL_BLOCK_TYPE}), + FLOWER_POT("minecraft:flower_pot", new BlockProperty[]{BlockProperty.UPDATE_BIT}), + CARROTS("minecraft:carrots", new BlockProperty[]{BlockProperty.GROWTH}), + POTATOES("minecraft:potatoes", new BlockProperty[]{BlockProperty.GROWTH}), + WOODEN_BUTTON("minecraft:wooden_button", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.BUTTON_PRESSED_BIT}), + SKULL("minecraft:skull", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.NO_DROP_BIT}), + ANVIL("minecraft:anvil", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DAMAGE}), + TRAPPED_CHEST("minecraft:trapped_chest", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + LIGHT_WEIGHTED_PRESSURE_PLATE("minecraft:light_weighted_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + HEAVY_WEIGHTED_PRESSURE_PLATE("minecraft:heavy_weighted_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + UNPOWERED_COMPARATOR("minecraft:unpowered_comparator", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OUTPUT_LIT_BIT, BlockProperty.OUTPUT_SUBTRACT_BIT}), + POWERED_COMPARATOR("minecraft:powered_comparator", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OUTPUT_LIT_BIT, BlockProperty.OUTPUT_SUBTRACT_BIT}), + DAYLIGHT_DETECTOR("minecraft:daylight_detector", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + REDSTONE_BLOCK("minecraft:redstone_block", new BlockProperty[]{}), + QUARTZ_ORE("minecraft:quartz_ore", new BlockProperty[]{}), + HOPPER("minecraft:hopper", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.TOGGLE_BIT}), + QUARTZ_BLOCK("minecraft:quartz_block", new BlockProperty[]{BlockProperty.CHISEL_TYPE, BlockProperty.PILLAR_AXIS}), + QUARTZ_STAIRS("minecraft:quartz_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + DOUBLE_WOODEN_SLAB("minecraft:double_wooden_slab", new BlockProperty[]{BlockProperty.WOOD_TYPE, BlockProperty.TOP_SLOT_BIT}), + WOODEN_SLAB("minecraft:wooden_slab", new BlockProperty[]{BlockProperty.WOOD_TYPE, BlockProperty.TOP_SLOT_BIT}), + STAINED_HARDENED_CLAY("minecraft:stained_hardened_clay", new BlockProperty[]{BlockProperty.COLOR}), + STAINED_GLASS_PANE("minecraft:stained_glass_pane", new BlockProperty[]{BlockProperty.COLOR}), + LEAVES2("minecraft:leaves2", new BlockProperty[]{BlockProperty.NEW_LEAF_TYPE, BlockProperty.PERSISTENT_BIT, BlockProperty.UPDATE_BIT}), + LOG2("minecraft:log2", new BlockProperty[]{BlockProperty.NEW_LOG_TYPE, BlockProperty.PILLAR_AXIS}), + ACACIA_STAIRS("minecraft:acacia_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + DARK_OAK_STAIRS("minecraft:dark_oak_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + SLIME("minecraft:slime", new BlockProperty[]{}), + IRON_TRAPDOOR("minecraft:iron_trapdoor", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OPEN_BIT, BlockProperty.UPSIDE_DOWN_BIT}), + PRISMARINE("minecraft:prismarine", new BlockProperty[]{BlockProperty.PRISMARINE_BLOCK_TYPE}), + SEALANTERN("minecraft:seaLantern", new BlockProperty[]{}), + HAY_BLOCK("minecraft:hay_block", new BlockProperty[]{BlockProperty.DEPRECATED, BlockProperty.PILLAR_AXIS}), + CARPET("minecraft:carpet", new BlockProperty[]{BlockProperty.COLOR}), + HARDENED_CLAY("minecraft:hardened_clay", new BlockProperty[]{}), + COAL_BLOCK("minecraft:coal_block", new BlockProperty[]{}), + PACKED_ICE("minecraft:packed_ice", new BlockProperty[]{}), + DOUBLE_PLANT("minecraft:double_plant", new BlockProperty[]{BlockProperty.DOUBLE_PLANT_TYPE, BlockProperty.UPPER_BLOCK_BIT}), + BANNER("minecraft:banner", new BlockProperty[]{}), + DAYLIGHT_DETECTOR_INVERTED("minecraft:daylight_detector_inverted", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + RED_SANDSTONE("minecraft:red_sandstone", new BlockProperty[]{BlockProperty.SAND_STONE_TYPE}), + RED_SANDSTONE_STAIRS("minecraft:red_sandstone_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + DOUBLE_STONE_SLAB2("minecraft:double_stone_slab2", new BlockProperty[]{BlockProperty.STONE_SLAB_TYPE_2, BlockProperty.TOP_SLOT_BIT}), + STONE_SLAB2("minecraft:stone_slab2", new BlockProperty[]{BlockProperty.STONE_SLAB_TYPE_2, BlockProperty.TOP_SLOT_BIT}), + SPRUCE_FENCE_GATE("minecraft:spruce_fence_gate", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.IN_WALL_BIT, BlockProperty.OPEN_BIT}), + BIRCH_FENCE_GATE("minecraft:birch_fence_gate", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.IN_WALL_BIT, BlockProperty.OPEN_BIT}), + JUNGLE_FENCE_GATE("minecraft:jungle_fence_gate", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.IN_WALL_BIT, BlockProperty.OPEN_BIT}), + DARK_OAK_FENCE_GATE("minecraft:dark_oak_fence_gate", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.IN_WALL_BIT, BlockProperty.OPEN_BIT}), + ACACIA_FENCE_GATE("minecraft:acacia_fence_gate", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.IN_WALL_BIT, BlockProperty.OPEN_BIT}), + REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.CONDITIONAL_BIT}), + CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.CONDITIONAL_BIT}), + HARD_GLASS_PANE("minecraft:hard_glass_pane", new BlockProperty[]{}), + HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", new BlockProperty[]{BlockProperty.COLOR}), + CHEMICAL_HEAT("minecraft:chemical_heat", new BlockProperty[]{}), + SPRUCE_DOOR("minecraft:spruce_door", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DOOR_HINGE_BIT, BlockProperty.OPEN_BIT, BlockProperty.UPPER_BLOCK_BIT}), + BIRCH_DOOR("minecraft:birch_door", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DOOR_HINGE_BIT, BlockProperty.OPEN_BIT, BlockProperty.UPPER_BLOCK_BIT}), + JUNGLE_DOOR("minecraft:jungle_door", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DOOR_HINGE_BIT, BlockProperty.OPEN_BIT, BlockProperty.UPPER_BLOCK_BIT}), + ACACIA_DOOR("minecraft:acacia_door", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DOOR_HINGE_BIT, BlockProperty.OPEN_BIT, BlockProperty.UPPER_BLOCK_BIT}), + DARK_OAK_DOOR("minecraft:dark_oak_door", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.DOOR_HINGE_BIT, BlockProperty.OPEN_BIT, BlockProperty.UPPER_BLOCK_BIT}), + GRASS_PATH("minecraft:grass_path", new BlockProperty[]{}), + FRAME("minecraft:frame", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.ITEM_FRAME_MAP_BIT}), + CHORUS_FLOWER("minecraft:chorus_flower", new BlockProperty[]{BlockProperty.AGE}), + PURPUR_BLOCK("minecraft:purpur_block", new BlockProperty[]{BlockProperty.CHISEL_TYPE, BlockProperty.PILLAR_AXIS}), + PURPUR_STAIRS("minecraft:purpur_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + SHULKER_BOX("minecraft:shulker_box", new BlockProperty[]{BlockProperty.COLOR}), + END_BRICKS("minecraft:end_bricks", new BlockProperty[]{}), + END_ROD("minecraft:end_rod", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + END_GATEWAY("minecraft:end_gateway", new BlockProperty[]{}), + B_210("minecraft:210", new BlockProperty[]{}), + B_211("minecraft:211", new BlockProperty[]{}), + B_212("minecraft:212", new BlockProperty[]{}), + MAGMA("minecraft:magma", new BlockProperty[]{}), + NETHER_WART_BLOCK("minecraft:nether_wart_block", new BlockProperty[]{}), + RED_NETHER_BRICK("minecraft:red_nether_brick", new BlockProperty[]{}), + BONE_BLOCK("minecraft:bone_block", new BlockProperty[]{BlockProperty.DEPRECATED, BlockProperty.PILLAR_AXIS}), + PURPLE_GLAZED_TERRACOTTA("minecraft:purple_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + WHITE_GLAZED_TERRACOTTA("minecraft:white_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + ORANGE_GLAZED_TERRACOTTA("minecraft:orange_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + MAGENTA_GLAZED_TERRACOTTA("minecraft:magenta_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + LIGHT_BLUE_GLAZED_TERRACOTTA("minecraft:light_blue_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + YELLOW_GLAZED_TERRACOTTA("minecraft:yellow_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + LIME_GLAZED_TERRACOTTA("minecraft:lime_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + PINK_GLAZED_TERRACOTTA("minecraft:pink_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + GRAY_GLAZED_TERRACOTTA("minecraft:gray_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + SILVER_GLAZED_TERRACOTTA("minecraft:silver_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + CYAN_GLAZED_TERRACOTTA("minecraft:cyan_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + B_230("minecraft:230", new BlockProperty[]{}), + BLUE_GLAZED_TERRACOTTA("minecraft:blue_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + BROWN_GLAZED_TERRACOTTA("minecraft:brown_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + GREEN_GLAZED_TERRACOTTA("minecraft:green_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + RED_GLAZED_TERRACOTTA("minecraft:red_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + BLACK_GLAZED_TERRACOTTA("minecraft:black_glazed_terracotta", new BlockProperty[]{BlockProperty.FACING_DIRECTION}), + CONCRETE("minecraft:concrete", new BlockProperty[]{BlockProperty.COLOR}), + CONCRETEPOWDER("minecraft:concretePowder", new BlockProperty[]{BlockProperty.COLOR}), + CHEMISTRY_TABLE("minecraft:chemistry_table", new BlockProperty[]{BlockProperty.CHEMISTRY_TABLE_TYPE, BlockProperty.DIRECTION}), + UNDERWATER_TORCH("minecraft:underwater_torch", new BlockProperty[]{BlockProperty.TORCH_FACING_DIRECTION}), + CHORUS_PLANT("minecraft:chorus_plant", new BlockProperty[]{}), + STAINED_GLASS("minecraft:stained_glass", new BlockProperty[]{BlockProperty.COLOR}), + B_242("minecraft:242", new BlockProperty[]{}), + PODZOL("minecraft:podzol", new BlockProperty[]{}), + BEETROOT("minecraft:beetroot", new BlockProperty[]{BlockProperty.GROWTH}), + STONECUTTER("minecraft:stonecutter", new BlockProperty[]{}), + GLOWINGOBSIDIAN("minecraft:glowingobsidian", new BlockProperty[]{}), + NETHERREACTOR("minecraft:netherreactor", new BlockProperty[]{}), + INFO_UPDATE("minecraft:info_update", new BlockProperty[]{}), + INFO_UPDATE2("minecraft:info_update2", new BlockProperty[]{}), + MOVINGBLOCK("minecraft:movingBlock", new BlockProperty[]{}), + OBSERVER("minecraft:observer", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.POWERED_BIT}), + STRUCTURE_BLOCK("minecraft:structure_block", new BlockProperty[]{BlockProperty.STRUCTURE_BLOCK_TYPE}), + HARD_GLASS("minecraft:hard_glass", new BlockProperty[]{}), + HARD_STAINED_GLASS("minecraft:hard_stained_glass", new BlockProperty[]{BlockProperty.COLOR}), + RESERVED6("minecraft:reserved6", new BlockProperty[]{}), + B_256("minecraft:256", new BlockProperty[]{}), + PRISMARINE_STAIRS("minecraft:prismarine_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + DARK_PRISMARINE_STAIRS("minecraft:dark_prismarine_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + PRISMARINE_BRICKS_STAIRS("minecraft:prismarine_bricks_stairs", new BlockProperty[]{BlockProperty.WEIRDO_DIRECTION, BlockProperty.UPSIDE_DOWN_BIT}), + STRIPPED_SPRUCE_LOG("minecraft:stripped_spruce_log", new BlockProperty[]{BlockProperty.PILLAR_AXIS}), + STRIPPED_BIRCH_LOG("minecraft:stripped_birch_log", new BlockProperty[]{BlockProperty.PILLAR_AXIS}), + STRIPPED_JUNGLE_LOG("minecraft:stripped_jungle_log", new BlockProperty[]{BlockProperty.PILLAR_AXIS}), + STRIPPED_ACACIA_LOG("minecraft:stripped_acacia_log", new BlockProperty[]{BlockProperty.PILLAR_AXIS}), + STRIPPED_DARK_OAK_LOG("minecraft:stripped_dark_oak_log", new BlockProperty[]{BlockProperty.PILLAR_AXIS}), + STRIPPED_OAK_LOG("minecraft:stripped_oak_log", new BlockProperty[]{BlockProperty.PILLAR_AXIS}), + BLUE_ICE("minecraft:blue_ice", new BlockProperty[]{}), + SEAGRASS("minecraft:seagrass", new BlockProperty[]{BlockProperty.SEA_GRASS_TYPE}), + CORAL("minecraft:coral", new BlockProperty[]{BlockProperty.CORAL_COLOR, BlockProperty.DEAD_BIT}), + CORAL_BLOCK("minecraft:coral_block", new BlockProperty[]{BlockProperty.CORAL_COLOR, BlockProperty.DEAD_BIT}), + CORAL_FAN("minecraft:coral_fan", new BlockProperty[]{BlockProperty.CORAL_COLOR, BlockProperty.CORAL_FAN_DIRECTION}), + CORAL_FAN_DEAD("minecraft:coral_fan_dead", new BlockProperty[]{BlockProperty.CORAL_COLOR, BlockProperty.CORAL_FAN_DIRECTION}), + CORAL_FAN_HANG("minecraft:coral_fan_hang", new BlockProperty[]{BlockProperty.CORAL_HANG_TYPE_BIT, BlockProperty.CORAL_DIRECTION, BlockProperty.DEAD_BIT}), + CORAL_FAN_HANG2("minecraft:coral_fan_hang2", new BlockProperty[]{BlockProperty.CORAL_HANG_TYPE_BIT, BlockProperty.CORAL_DIRECTION, BlockProperty.DEAD_BIT}), + CORAL_FAN_HANG3("minecraft:coral_fan_hang3", new BlockProperty[]{BlockProperty.CORAL_HANG_TYPE_BIT, BlockProperty.CORAL_DIRECTION, BlockProperty.DEAD_BIT}), + KELP("minecraft:kelp", new BlockProperty[]{BlockProperty.KELP_AGE}), + DRIED_KELP_BLOCK("minecraft:dried_kelp_block", new BlockProperty[]{}), + ACACIA_BUTTON("minecraft:acacia_button", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.BUTTON_PRESSED_BIT}), + BIRCH_BUTTON("minecraft:birch_button", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.BUTTON_PRESSED_BIT}), + DARK_OAK_BUTTON("minecraft:dark_oak_button", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.BUTTON_PRESSED_BIT}), + JUNGLE_BUTTON("minecraft:jungle_button", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.BUTTON_PRESSED_BIT}), + SPRUCE_BUTTON("minecraft:spruce_button", new BlockProperty[]{BlockProperty.FACING_DIRECTION, BlockProperty.BUTTON_PRESSED_BIT}), + ACACIA_TRAPDOOR("minecraft:acacia_trapdoor", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OPEN_BIT, BlockProperty.UPSIDE_DOWN_BIT}), + BIRCH_TRAPDOOR("minecraft:birch_trapdoor", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OPEN_BIT, BlockProperty.UPSIDE_DOWN_BIT}), + DARK_OAK_TRAPDOOR("minecraft:dark_oak_trapdoor", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OPEN_BIT, BlockProperty.UPSIDE_DOWN_BIT}), + JUNGLE_TRAPDOOR("minecraft:jungle_trapdoor", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OPEN_BIT, BlockProperty.UPSIDE_DOWN_BIT}), + SPRUCE_TRAPDOOR("minecraft:spruce_trapdoor", new BlockProperty[]{BlockProperty.DIRECTION, BlockProperty.OPEN_BIT, BlockProperty.UPSIDE_DOWN_BIT}), + ACACIA_PRESSURE_PLATE("minecraft:acacia_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + BIRCH_PRESSURE_PLATE("minecraft:birch_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + DARK_OAK_PRESSURE_PLATE("minecraft:dark_oak_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + JUNGLE_PRESSURE_PLATE("minecraft:jungle_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + SPRUCE_PRESSURE_PLATE("minecraft:spruce_pressure_plate", new BlockProperty[]{BlockProperty.REDSTONE_SIGNAL}), + CARVED_PUMPKIN("minecraft:carved_pumpkin", new BlockProperty[]{BlockProperty.DIRECTION}), + SEA_PICKLE("minecraft:sea_pickle", new BlockProperty[]{BlockProperty.CLUSTER_COUNT, BlockProperty.DEAD_BIT}), + UNKNOWN("blocktopograph:unknown", new BlockProperty[0]); + + private static final Map blockTypes = new HashMap<>(); + + private final String name; + + private final BlockProperty[] knownProperties; + + static { + for (var block : BlockType.values()) blockTypes.put(block.name, block); + } + + BlockType(String name, BlockProperty[] knownProperties) { + this.name = name; + this.knownProperties = knownProperties; + } + + @Nullable + public static BlockType get(String name) { + return blockTypes.get(name); + } + + public String getName() { + return name; + } + + public BlockProperty[] getKnownProperties() { + return knownProperties; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockWithStatesToLegacyBlockMapper.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockWithStatesToLegacyBlockMapper.java new file mode 100644 index 00000000..0e60ab48 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/BlockWithStatesToLegacyBlockMapper.java @@ -0,0 +1,4814 @@ +package com.mithrilmania.blocktopograph.block; + +import android.util.Pair; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.List; + +public class BlockWithStatesToLegacyBlockMapper { + + private static Hashtable[]> mMapTypeToBlocks; + + static { + mMapTypeToBlocks = new Hashtable<>(); + mMapTypeToBlocks.put("air", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_0_0_AIR + ) + }); + mMapTypeToBlocks.put("stone", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("stone_type", "stone").build(), + KnownBlockRepr.B_1_0_STONE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_type", "granite").build(), + KnownBlockRepr.B_1_1_STONE_GRANITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_type", "granite_smooth").build(), + KnownBlockRepr.B_1_2_STONE_GRANITE_SMOOTH + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_type", "diorite").build(), + KnownBlockRepr.B_1_3_STONE_DIORITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_type", "diorite_smooth").build(), + KnownBlockRepr.B_1_4_STONE_DIORITE_SMOOTH + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_type", "andesite").build(), + KnownBlockRepr.B_1_5_STONE_ANDESITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_type", "andesite_smooth").build(), + KnownBlockRepr.B_1_6_STONE_ANDESITE_SMOOTH + ) + }); + mMapTypeToBlocks.put("grass", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_2_0_GRASS + ) + }); + mMapTypeToBlocks.put("dirt", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("dirt_type", "normal").build(), + KnownBlockRepr.B_3_0_DIRT + ) + }); + mMapTypeToBlocks.put("cobblestone", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_4_0_COBBLESTONE + ) + }); + mMapTypeToBlocks.put("planks", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "oak").build(), + KnownBlockRepr.B_5_0_PLANKS_OAK + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "spruce").build(), + KnownBlockRepr.B_5_1_PLANKS_SPRUCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "birch").build(), + KnownBlockRepr.B_5_2_PLANKS_BIRCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "jungle").build(), + KnownBlockRepr.B_5_3_PLANKS_JUNGLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "acacia").build(), + KnownBlockRepr.B_5_4_PLANKS_ACACIA + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "dark_oak").build(), + KnownBlockRepr.B_5_5_PLANKS_BIG_OAK + ) + }); + mMapTypeToBlocks.put("sapling", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("sapling_type", "oak").addByte("age_bit", (byte) 0).build(), + KnownBlockRepr.B_6_0_SAPLING_OAK + ), + new Pair<>( + new BlockStateBuilder().addProperty("sapling_type", "spruce").addByte("age_bit", (byte) 0).build(), + KnownBlockRepr.B_6_1_SAPLING_SPRUCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("sapling_type", "birch").addByte("age_bit", (byte) 0).build(), + KnownBlockRepr.B_6_2_SAPLING_BIRCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("sapling_type", "jungle").addByte("age_bit", (byte) 0).build(), + KnownBlockRepr.B_6_3_SAPLING_JUNGLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("sapling_type", "acacia").addByte("age_bit", (byte) 0).build(), + KnownBlockRepr.B_6_4_SAPLING_ACACIA + ), + new Pair<>( + new BlockStateBuilder().addProperty("sapling_type", "dark_oak").addByte("age_bit", (byte) 0).build(), + KnownBlockRepr.B_6_5_SAPLING_BIG_OAK + ) + }); + mMapTypeToBlocks.put("bedrock", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("infiniburn_bit", (byte) 0).build(), + KnownBlockRepr.B_7_0_BEDROCK + ) + }); + mMapTypeToBlocks.put("flowing_water", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("liquid_depth", 0).build(), + KnownBlockRepr.B_8_0_FLOWING_WATER + ) + }); + mMapTypeToBlocks.put("water", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("liquid_depth", 0).build(), + KnownBlockRepr.B_9_0_WATER + ) + }); + mMapTypeToBlocks.put("flowing_lava", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("liquid_depth", 0).build(), + KnownBlockRepr.B_10_0_FLOWING_LAVA + ) + }); + mMapTypeToBlocks.put("lava", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("liquid_depth", 0).build(), + KnownBlockRepr.B_11_0_LAVA + ) + }); + mMapTypeToBlocks.put("sand", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("sand_type", "normal").build(), + KnownBlockRepr.B_12_0_SAND_DEFAULT + ), + new Pair<>( + new BlockStateBuilder().addProperty("sand_type", "red").build(), + KnownBlockRepr.B_12_1_SAND_RED + ) + }); + mMapTypeToBlocks.put("gravel", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_13_0_GRAVEL + ) + }); + mMapTypeToBlocks.put("gold_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_14_0_GOLD_ORE + ) + }); + mMapTypeToBlocks.put("iron_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_15_0_IRON_ORE + ) + }); + mMapTypeToBlocks.put("coal_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_16_0_COAL_ORE + ) + }); + mMapTypeToBlocks.put("log", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("old_log_type", "oak").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_17_0_LOG_OAK + ), + new Pair<>( + new BlockStateBuilder().addProperty("old_log_type", "spruce").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_17_1_LOG_SPRUCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("old_log_type", "birch").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_17_2_LOG_BIRCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("old_log_type", "jungle").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_17_3_LOG_JUNGLE + ) + }); + mMapTypeToBlocks.put("leaves", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("old_leaf_type", "oak").addByte("persistent_bit", (byte) 0).addByte("update_bit", (byte) 0).build(), + KnownBlockRepr.B_18_0_LEAVES_OAK + ), + new Pair<>( + new BlockStateBuilder().addProperty("old_leaf_type", "spruce").addByte("persistent_bit", (byte) 0).addByte("update_bit", (byte) 0).build(), + KnownBlockRepr.B_18_1_LEAVES_SPRUCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("old_leaf_type", "birch").addByte("persistent_bit", (byte) 0).addByte("update_bit", (byte) 0).build(), + KnownBlockRepr.B_18_2_LEAVES_BIRCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("old_leaf_type", "jungle").addByte("persistent_bit", (byte) 0).addByte("update_bit", (byte) 0).build(), + KnownBlockRepr.B_18_3_LEAVES_JUNGLE + ) + }); + mMapTypeToBlocks.put("sponge", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("sponge_type", "dry").build(), + KnownBlockRepr.B_19_0_SPONGE_DRY + ), + new Pair<>( + new BlockStateBuilder().addProperty("sponge_type", "wet").build(), + KnownBlockRepr.B_19_1_SPONGE_WET + ) + }); + mMapTypeToBlocks.put("glass", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_20_0_GLASS + ) + }); + mMapTypeToBlocks.put("lapis_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_21_0_LAPIS_ORE + ) + }); + mMapTypeToBlocks.put("lapis_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_22_0_LAPIS_BLOCK + ) + }); + mMapTypeToBlocks.put("dispenser", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("triggered_bit", (byte) 0).build(), + KnownBlockRepr.B_23_0_DISPENSER + ) + }); + mMapTypeToBlocks.put("sandstone", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("sand_stone_type", "default").build(), + KnownBlockRepr.B_24_0_SANDSTONE_DEFAULT + ), + new Pair<>( + new BlockStateBuilder().addProperty("sand_stone_type", "heiroglyphs").build(), + KnownBlockRepr.B_24_1_SANDSTONE_CHISELED + ), + new Pair<>( + new BlockStateBuilder().addProperty("sand_stone_type", "cut").build(), + KnownBlockRepr.B_24_2_SANDSTONE_SMOOTH + ) + }); + mMapTypeToBlocks.put("noteblock", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_25_0_NOTEBLOCK + ) + }); + mMapTypeToBlocks.put("bed", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("head_piece_bit", (byte) 0).addByte("occupied_bit", (byte) 0).build(), + KnownBlockRepr.B_26_0_BED + ) + }); + mMapTypeToBlocks.put("golden_rail", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("rail_direction", 0).addByte("rail_data_bit", (byte) 0).build(), + KnownBlockRepr.B_27_0_GOLDEN_RAIL + ) + }); + mMapTypeToBlocks.put("detector_rail", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("rail_direction", 0).addByte("rail_data_bit", (byte) 0).build(), + KnownBlockRepr.B_28_0_DETECTOR_RAIL + ) + }); + mMapTypeToBlocks.put("sticky_piston", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_29_0_STICKY_PISTON + ) + }); + mMapTypeToBlocks.put("web", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_30_0_WEB + ) + }); + mMapTypeToBlocks.put("tallgrass", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("tall_grass_type", "tall").build(), + KnownBlockRepr.B_31_1_TALLGRASS_FERN + ), + new Pair<>( + new BlockStateBuilder().addProperty("tall_grass_type", "fern").build(), + KnownBlockRepr.B_31_2_TALLGRASS_GRASS + ) + }); + mMapTypeToBlocks.put("deadbush", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_32_0_DEADBUSH + ) + }); + mMapTypeToBlocks.put("piston", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_33_0_PISTON + ) + }); + mMapTypeToBlocks.put("pistonArmCollision", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_34_0_PISTONARMCOLLISION + ) + }); + mMapTypeToBlocks.put("wool", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_35_0_WOOL_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_35_1_WOOL_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_35_2_WOOL_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_35_3_WOOL_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_35_4_WOOL_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_35_5_WOOL_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_35_6_WOOL_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_35_7_WOOL_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_35_8_WOOL_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_35_9_WOOL_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_35_10_WOOL_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_35_11_WOOL_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_35_12_WOOL_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_35_13_WOOL_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_35_14_WOOL_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_35_15_WOOL_BLACK + ) + }); + mMapTypeToBlocks.put("element_0", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_0_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_1_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_2_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_3_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_4_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_5_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_6_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_7_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_8_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_9_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_10_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_11_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_12_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_13_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_14_ELEMENT0 + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_36_15_ELEMENT0 + ) + }); + mMapTypeToBlocks.put("yellow_flower", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_37_0_YELLOW_FLOWER + ) + }); + mMapTypeToBlocks.put("red_flower", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "poppy").build(), + KnownBlockRepr.B_38_0_RED_FLOWER_POPPY + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "orchid").build(), + KnownBlockRepr.B_38_1_RED_FLOWER_BLUE_ORCHID + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "allium").build(), + KnownBlockRepr.B_38_2_RED_FLOWER_ALLIUM + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "houstonia").build(), + KnownBlockRepr.B_38_3_RED_FLOWER_HOUSTONIA + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "tulip_red").build(), + KnownBlockRepr.B_38_4_RED_FLOWER_TULIP_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "tulip_orange").build(), + KnownBlockRepr.B_38_5_RED_FLOWER_TULIP_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "tulip_white").build(), + KnownBlockRepr.B_38_6_RED_FLOWER_TULIP_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "tulip_pink").build(), + KnownBlockRepr.B_38_7_RED_FLOWER_TULIP_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("flower_type", "oxeye").build(), + KnownBlockRepr.B_38_8_RED_FLOWER_OXEYE_DAISY + ) + }); + mMapTypeToBlocks.put("brown_mushroom", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_39_0_BROWN_MUSHROOM + ) + }); + mMapTypeToBlocks.put("red_mushroom", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_40_0_RED_MUSHROOM + ) + }); + mMapTypeToBlocks.put("gold_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_41_0_GOLD_BLOCK + ) + }); + mMapTypeToBlocks.put("iron_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_42_0_IRON_BLOCK + ) + }); + mMapTypeToBlocks.put("double_stone_slab", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "smooth_stone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_0_DOUBLE_STONE_SLAB_STONE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "sandstone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_1_DOUBLE_STONE_SLAB_SAND + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "wood").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_2_DOUBLE_STONE_SLAB_WOOD + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "cobblestone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_3_DOUBLE_STONE_SLAB_COBBLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "brick").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_4_DOUBLE_STONE_SLAB_BRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "stone_brick").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_5_DOUBLE_STONE_SLAB_SMOOTH_STONE_BRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "quartz").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_6_DOUBLE_STONE_SLAB_QUARTZ + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "nether_brick").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_43_7_DOUBLE_STONE_SLAB_NETHER_BRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "smooth_stone").addByte("top_slot_bit", (byte) 1).build(), + KnownBlockRepr.B_43_8_DOUBLE_STONE_SLAB_RED_SANDSTONE + ) + }); + mMapTypeToBlocks.put("stone_slab", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "smooth_stone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_0_STONE_SLAB_STONE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "sandstone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_1_STONE_SLAB_SAND + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "wood").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_2_STONE_SLAB_WOOD + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "cobblestone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_3_STONE_SLAB_COBBLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "brick").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_4_STONE_SLAB_BRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "stone_brick").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_5_STONE_SLAB_SMOOTH_STONE_BRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "quartz").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_6_STONE_SLAB_QUARTZ + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type", "nether_brick").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_44_7_STONE_SLAB_NETHER_BRICK + ) + }); + mMapTypeToBlocks.put("brick_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_45_0_BRICK_BLOCK + ) + }); + mMapTypeToBlocks.put("tnt", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("allow_underwater_bit", (byte) 0).addByte("explode_bit", (byte) 0).build(), + KnownBlockRepr.B_46_0_TNT + ) + }); + mMapTypeToBlocks.put("bookshelf", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_47_0_BOOKSHELF + ) + }); + mMapTypeToBlocks.put("mossy_cobblestone", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_48_0_MOSSY_COBBLESTONE + ) + }); + mMapTypeToBlocks.put("obsidian", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_49_0_OBSIDIAN + ) + }); + mMapTypeToBlocks.put("torch", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "unknown").build(), + KnownBlockRepr.B_50_0_TORCH + ) + }); + mMapTypeToBlocks.put("fire", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("age", 0).build(), + KnownBlockRepr.B_51_0_FIRE + ) + }); + mMapTypeToBlocks.put("mob_spawner", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_52_0_MOB_SPAWNER + ) + }); + mMapTypeToBlocks.put("oak_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_53_0_OAK_STAIRS + ) + }); + mMapTypeToBlocks.put("chest", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_54_0_CHEST + ) + }); + mMapTypeToBlocks.put("redstone_wire", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_55_0_REDSTONE_WIRE + ) + }); + mMapTypeToBlocks.put("diamond_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_56_0_DIAMOND_ORE + ) + }); + mMapTypeToBlocks.put("diamond_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_57_0_DIAMOND_BLOCK + ) + }); + mMapTypeToBlocks.put("crafting_table", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_58_0_CRAFTING_TABLE + ) + }); + mMapTypeToBlocks.put("wheat", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("growth", 0).build(), + KnownBlockRepr.B_59_0_WHEAT + ) + }); + mMapTypeToBlocks.put("farmland", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("moisturized_amount", 0).build(), + KnownBlockRepr.B_60_0_FARMLAND + ) + }); + mMapTypeToBlocks.put("furnace", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_61_0_FURNACE + ) + }); + mMapTypeToBlocks.put("lit_furnace", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_62_0_LIT_FURNACE + ) + }); + mMapTypeToBlocks.put("standing_sign", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("ground_sign_direction", 0).build(), + KnownBlockRepr.B_63_0_STANDING_SIGN + ) + }); + mMapTypeToBlocks.put("wooden_door", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("door_hinge_bit", (byte) 0).addByte("open_bit", (byte) 0).addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_64_0_WOODEN_DOOR + ) + }); + mMapTypeToBlocks.put("ladder", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_65_0_LADDER + ) + }); + mMapTypeToBlocks.put("rail", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("rail_direction", 0).build(), + KnownBlockRepr.B_66_0_RAIL + ) + }); + mMapTypeToBlocks.put("stone_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_67_0_STONE_STAIRS + ) + }); + mMapTypeToBlocks.put("wall_sign", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_68_0_WALL_SIGN + ) + }); + mMapTypeToBlocks.put("lever", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("lever_direction", "down_east_west").addByte("open_bit", (byte) 0).build(), + KnownBlockRepr.B_69_0_LEVER + ) + }); + mMapTypeToBlocks.put("stone_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_70_0_STONE_PRESSURE_PLATE + ) + }); + mMapTypeToBlocks.put("iron_door", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("door_hinge_bit", (byte) 0).addByte("open_bit", (byte) 0).addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_71_0_IRON_DOOR + ) + }); + mMapTypeToBlocks.put("wooden_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_72_0_WOODEN_PRESSURE_PLATE + ) + }); + mMapTypeToBlocks.put("redstone_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_73_0_REDSTONE_ORE + ) + }); + mMapTypeToBlocks.put("lit_redstone_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_74_0_LIT_REDSTONE_ORE + ) + }); + mMapTypeToBlocks.put("unlit_redstone_torch", new Pair[]{ + + }); + mMapTypeToBlocks.put("redstone_torch", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "unknown").build(), + KnownBlockRepr.B_76_0_REDSTONE_TORCH + ) + }); + mMapTypeToBlocks.put("stone_button", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_77_0_STONE_BUTTON + ) + }); + mMapTypeToBlocks.put("snow_layer", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("covered_bit", (byte) 0).addInt("height", 0).build(), + KnownBlockRepr.B_78_0_SNOW_LAYER + ) + }); + mMapTypeToBlocks.put("ice", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_79_0_ICE + ) + }); + mMapTypeToBlocks.put("snow", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_80_0_SNOW + ) + }); + mMapTypeToBlocks.put("cactus", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("age", 0).build(), + KnownBlockRepr.B_81_0_CACTUS + ) + }); + mMapTypeToBlocks.put("clay", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_82_0_CLAY + ) + }); + mMapTypeToBlocks.put("reeds", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("age", 0).build(), + KnownBlockRepr.B_83_0_REEDS + ) + }); + mMapTypeToBlocks.put("jukebox", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_84_0_JUKEBOX + ) + }); + mMapTypeToBlocks.put("fence", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "oak").build(), + KnownBlockRepr.B_85_0_FENCE_FENCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "spruce").build(), + KnownBlockRepr.B_85_1_FENCE_SPRUCE_FENCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "birch").build(), + KnownBlockRepr.B_85_2_FENCE_BIRCH_FENCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "jungle").build(), + KnownBlockRepr.B_85_3_FENCE_JUNGLE_FENCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "acacia").build(), + KnownBlockRepr.B_85_4_FENCE_ACACIA_FENCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "dark_oak").build(), + KnownBlockRepr.B_85_5_FENCE_DARK_OAK_FENCE + ) + }); + mMapTypeToBlocks.put("pumpkin", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).build(), + KnownBlockRepr.B_86_0_PUMPKIN + ) + }); + mMapTypeToBlocks.put("netherrack", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_87_0_NETHERRACK + ) + }); + mMapTypeToBlocks.put("soul_sand", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_88_0_SOUL_SAND + ) + }); + mMapTypeToBlocks.put("glowstone", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_89_0_GLOWSTONE + ) + }); + mMapTypeToBlocks.put("portal", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("portal_axis", "unknown").build(), + KnownBlockRepr.B_90_0_PORTAL + ) + }); + mMapTypeToBlocks.put("lit_pumpkin", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).build(), + KnownBlockRepr.B_91_0_LIT_PUMPKIN + ) + }); + mMapTypeToBlocks.put("cake", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("bite_counter", 0).build(), + KnownBlockRepr.B_92_0_CAKE + ) + }); + mMapTypeToBlocks.put("unpowered_repeater", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addInt("repeater_delay", 0).build(), + KnownBlockRepr.B_93_0_UNPOWERED_REPEATER + ) + }); + mMapTypeToBlocks.put("powered_repeater", new Pair[]{ + + }); + mMapTypeToBlocks.put("invisibleBedrock", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_95_0_INVISIBLEBEDROCK + ) + }); + mMapTypeToBlocks.put("trapdoor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_96_0_TRAPDOOR + ) + }); + mMapTypeToBlocks.put("monster_egg", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("monster_egg_stone_type", "stone").build(), + KnownBlockRepr.B_97_0_MONSTER_EGG_STONE + ), + new Pair<>( + new BlockStateBuilder().addProperty("monster_egg_stone_type", "cobblestone").build(), + KnownBlockRepr.B_97_1_MONSTER_EGG_COBBLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("monster_egg_stone_type", "stone_brick").build(), + KnownBlockRepr.B_97_2_MONSTER_EGG_BRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("monster_egg_stone_type", "mossy_stone_brick").build(), + KnownBlockRepr.B_97_3_MONSTER_EGG_MOSSYBRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("monster_egg_stone_type", "cracked_stone_brick").build(), + KnownBlockRepr.B_97_4_MONSTER_EGG_CRACKEDBRICK + ), + new Pair<>( + new BlockStateBuilder().addProperty("monster_egg_stone_type", "chiseled_stone_brick").build(), + KnownBlockRepr.B_97_5_MONSTER_EGG_CHISELEDBRICK + ) + }); + mMapTypeToBlocks.put("stonebrick", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("stone_brick_type", "default").build(), + KnownBlockRepr.B_98_0_STONEBRICK_DEFAULT + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_brick_type", "mossy").build(), + KnownBlockRepr.B_98_1_STONEBRICK_MOSSY + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_brick_type", "cracked").build(), + KnownBlockRepr.B_98_2_STONEBRICK_CRACKED + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_brick_type", "chiseled").build(), + KnownBlockRepr.B_98_3_STONEBRICK_CHISELED + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_brick_type", "smooth").build(), + KnownBlockRepr.B_98_4_STONEBRICK_SMOOTH + ) + }); + mMapTypeToBlocks.put("brown_mushroom_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("huge_mushroom_bits", 0).build(), + KnownBlockRepr.B_99_0_BROWN_MUSHROOM_BLOCK + ) + }); + mMapTypeToBlocks.put("red_mushroom_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("huge_mushroom_bits", 0).build(), + KnownBlockRepr.B_100_0_RED_MUSHROOM_BLOCK + ) + }); + mMapTypeToBlocks.put("iron_bars", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_101_0_IRON_BARS + ) + }); + mMapTypeToBlocks.put("glass_pane", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_102_0_GLASS_PANE + ) + }); + mMapTypeToBlocks.put("melon_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_103_0_MELON_BLOCK + ) + }); + mMapTypeToBlocks.put("pumpkin_stem", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("growth", 0).build(), + KnownBlockRepr.B_104_0_PUMPKIN_STEM + ) + }); + mMapTypeToBlocks.put("melon_stem", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("growth", 0).build(), + KnownBlockRepr.B_105_0_MELON_STEM + ) + }); + mMapTypeToBlocks.put("vine", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("vine_direction_bits", 0).build(), + KnownBlockRepr.B_106_0_VINE + ) + }); + mMapTypeToBlocks.put("fence_gate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("in_wall_bit", (byte) 0).addByte("open_bit", (byte) 0).build(), + KnownBlockRepr.B_107_0_FENCE_GATE + ) + }); + mMapTypeToBlocks.put("brick_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_108_0_BRICK_STAIRS + ) + }); + mMapTypeToBlocks.put("stone_brick_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_109_0_STONE_BRICK_STAIRS + ) + }); + mMapTypeToBlocks.put("mycelium", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_110_0_MYCELIUM + ) + }); + mMapTypeToBlocks.put("waterlily", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_111_0_WATERLILY + ) + }); + mMapTypeToBlocks.put("nether_brick", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_112_0_NETHER_BRICK + ) + }); + mMapTypeToBlocks.put("nether_brick_fence", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_113_0_NETHER_BRICK_FENCE + ) + }); + mMapTypeToBlocks.put("nether_brick_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_114_0_NETHER_BRICK_STAIRS + ) + }); + mMapTypeToBlocks.put("nether_wart", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("age", 0).build(), + KnownBlockRepr.B_115_0_NETHER_WART + ) + }); + mMapTypeToBlocks.put("enchanting_table", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_116_0_ENCHANTING_TABLE + ) + }); + mMapTypeToBlocks.put("brewing_stand", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("brewing_stand_slot_a_bit", (byte) 0).addByte("brewing_stand_slot_b_bit", (byte) 0).addByte("brewing_stand_slot_c_bit", (byte) 0).build(), + KnownBlockRepr.B_117_0_BREWING_STAND + ) + }); + mMapTypeToBlocks.put("cauldron", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("cauldron_liquid", "water").addInt("fill_level", 0).build(), + KnownBlockRepr.B_118_0_CAULDRON + ) + }); + mMapTypeToBlocks.put("end_portal", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_119_0_END_PORTAL + ) + }); + mMapTypeToBlocks.put("end_portal_frame", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("end_portal_eye_bit", (byte) 0).build(), + KnownBlockRepr.B_120_0_END_PORTAL_FRAME + ) + }); + mMapTypeToBlocks.put("end_stone", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_121_0_END_STONE + ) + }); + mMapTypeToBlocks.put("dragon_egg", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_122_0_DRAGON_EGG + ) + }); + mMapTypeToBlocks.put("redstone_lamp", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_123_0_REDSTONE_LAMP + ) + }); + mMapTypeToBlocks.put("lit_redstone_lamp", new Pair[]{ + + }); + mMapTypeToBlocks.put("dropper", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("triggered_bit", (byte) 0).build(), + KnownBlockRepr.B_125_0_DROPPER + ) + }); + mMapTypeToBlocks.put("activator_rail", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("rail_direction", 0).addByte("rail_data_bit", (byte) 0).build(), + KnownBlockRepr.B_126_0_ACTIVATOR_RAIL + ) + }); + mMapTypeToBlocks.put("cocoa", new Pair[]{ + + }); + mMapTypeToBlocks.put("sandstone_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_128_0_SANDSTONE_STAIRS + ) + }); + mMapTypeToBlocks.put("emerald_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_129_0_EMERALD_ORE + ) + }); + mMapTypeToBlocks.put("ender_chest", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_130_0_ENDER_CHEST + ) + }); + mMapTypeToBlocks.put("tripwire_hook", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("attached_bit", (byte) 0).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_131_0_TRIPWIRE_HOOK + ) + }); + mMapTypeToBlocks.put("tripWire", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("attached_bit", (byte) 0).addByte("disarmed_bit", (byte) 0).addByte("powered_bit", (byte) 0).addByte("suspended_bit", (byte) 0).build(), + KnownBlockRepr.B_132_0_TRIPWIRE + ) + }); + mMapTypeToBlocks.put("emerald_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_133_0_EMERALD_BLOCK + ) + }); + mMapTypeToBlocks.put("spruce_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_134_0_SPRUCE_STAIRS + ) + }); + mMapTypeToBlocks.put("birch_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_135_0_BIRCH_STAIRS + ) + }); + mMapTypeToBlocks.put("jungle_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_136_0_JUNGLE_STAIRS + ) + }); + mMapTypeToBlocks.put("beacon", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_138_0_BEACON + ) + }); + mMapTypeToBlocks.put("cobblestone_wall", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("wall_block_type", "cobblestone").build(), + KnownBlockRepr.B_139_0_COBBLESTONE_WALL_NORMAL + ), + new Pair<>( + new BlockStateBuilder().addProperty("wall_block_type", "mossy_cobblestone").build(), + KnownBlockRepr.B_139_1_COBBLESTONE_WALL_MOSSY + ) + }); + mMapTypeToBlocks.put("flower_pot", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("update_bit", (byte) 0).build(), + KnownBlockRepr.B_140_0_FLOWER_POT + ) + }); + mMapTypeToBlocks.put("carrots", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("growth", 0).build(), + KnownBlockRepr.B_141_0_CARROTS + ) + }); + mMapTypeToBlocks.put("potatoes", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("growth", 0).build(), + KnownBlockRepr.B_142_0_POTATOES + ) + }); + mMapTypeToBlocks.put("wooden_button", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_143_0_WOODEN_BUTTON + ) + }); + mMapTypeToBlocks.put("skull", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("no_drop_bit", (byte) 0).build(), + KnownBlockRepr.B_144_0_SKULL + ) + }); + mMapTypeToBlocks.put("anvil", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addProperty("damage", "undamaged").build(), + KnownBlockRepr.B_145_0_ANVIL_INTACT + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addProperty("damage", "slightly_damaged").build(), + KnownBlockRepr.B_145_4_ANVIL_SLIGHTLY_DAMAGED + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addProperty("damage", "very_damaged").build(), + KnownBlockRepr.B_145_8_ANVIL_VERY_DAMAGED + ) + }); + mMapTypeToBlocks.put("trapped_chest", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_146_0_TRAPPED_CHEST + ) + }); + mMapTypeToBlocks.put("light_weighted_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_147_0_LIGHT_WEIGHTED_PRESSURE_PLATE + ) + }); + mMapTypeToBlocks.put("heavy_weighted_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_148_0_HEAVY_WEIGHTED_PRESSURE_PLATE + ) + }); + mMapTypeToBlocks.put("unpowered_comparator", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("output_lit_bit", (byte) 0).addByte("output_subtract_bit", (byte) 0).build(), + KnownBlockRepr.B_149_0_UNPOWERED_COMPARATOR + ) + }); + mMapTypeToBlocks.put("powered_comparator", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("output_lit_bit", (byte) 0).addByte("output_subtract_bit", (byte) 0).build(), + KnownBlockRepr.B_150_0_POWERED_COMPARATOR + ) + }); + mMapTypeToBlocks.put("daylight_detector", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_151_0_DAYLIGHT_DETECTOR + ) + }); + mMapTypeToBlocks.put("redstone_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_152_0_REDSTONE_BLOCK + ) + }); + mMapTypeToBlocks.put("quartz_ore", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_153_0_QUARTZ_ORE + ) + }); + mMapTypeToBlocks.put("hopper", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("toggle_bit", (byte) 0).build(), + KnownBlockRepr.B_154_0_HOPPER + ) + }); + mMapTypeToBlocks.put("quartz_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "default").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_155_0_QUARTZ_BLOCK_DEFAULT + ), + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "chiseled").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_155_1_QUARTZ_BLOCK_CHISELED + ), + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "lines").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_155_2_QUARTZ_BLOCK_LINES + ), + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "smooth").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_155_3_QUARTZ_BLOCK_DEFAULT + ) + }); + mMapTypeToBlocks.put("quartz_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_156_0_QUARTZ_STAIRS + ) + }); + mMapTypeToBlocks.put("double_wooden_slab", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "oak").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_157_0_DOUBLE_WOODEN_SLAB_OAK + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "spruce").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_157_1_DOUBLE_WOODEN_SLAB_SPRUCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "birch").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_157_2_DOUBLE_WOODEN_SLAB_BIRCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "jungle").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_157_3_DOUBLE_WOODEN_SLAB_JUNGLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "acacia").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_157_4_DOUBLE_WOODEN_SLAB_ACACIA + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "dark_oak").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_157_5_DOUBLE_WOODEN_SLAB_BIG_OAK + ) + }); + mMapTypeToBlocks.put("wooden_slab", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "oak").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_158_0_WOODEN_SLAB_OAK + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "spruce").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_158_1_WOODEN_SLAB_SPRUCE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "birch").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_158_2_WOODEN_SLAB_BIRCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "jungle").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_158_3_WOODEN_SLAB_JUNGLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "acacia").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_158_4_WOODEN_SLAB_ACACIA + ), + new Pair<>( + new BlockStateBuilder().addProperty("wood_type", "dark_oak").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_158_5_WOODEN_SLAB_BIG_OAK + ) + }); + mMapTypeToBlocks.put("stained_hardened_clay", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_159_0_STAINED_HARDENED_CLAY_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_159_1_STAINED_HARDENED_CLAY_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_159_2_STAINED_HARDENED_CLAY_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_159_3_STAINED_HARDENED_CLAY_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_159_4_STAINED_HARDENED_CLAY_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_159_5_STAINED_HARDENED_CLAY_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_159_6_STAINED_HARDENED_CLAY_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_159_7_STAINED_HARDENED_CLAY_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_159_8_STAINED_HARDENED_CLAY_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_159_9_STAINED_HARDENED_CLAY_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_159_10_STAINED_HARDENED_CLAY_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_159_11_STAINED_HARDENED_CLAY_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_159_12_STAINED_HARDENED_CLAY_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_159_13_STAINED_HARDENED_CLAY_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_159_14_STAINED_HARDENED_CLAY_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_159_15_STAINED_HARDENED_CLAY_BLACK + ) + }); + mMapTypeToBlocks.put("stained_glass_pane", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_160_0_STAINED_GLASS_PANE_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_160_1_STAINED_GLASS_PANE_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_160_2_STAINED_GLASS_PANE_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_160_3_STAINED_GLASS_PANE_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_160_4_STAINED_GLASS_PANE_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_160_5_STAINED_GLASS_PANE_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_160_6_STAINED_GLASS_PANE_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_160_7_STAINED_GLASS_PANE_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_160_8_STAINED_GLASS_PANE_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_160_9_STAINED_GLASS_PANE_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_160_10_STAINED_GLASS_PANE_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_160_11_STAINED_GLASS_PANE_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_160_12_STAINED_GLASS_PANE_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_160_13_STAINED_GLASS_PANE_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_160_14_STAINED_GLASS_PANE_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_160_15_STAINED_GLASS_PANE_BLACK + ) + }); + mMapTypeToBlocks.put("leaves2", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("new_leaf_type", "acacia").addByte("persistent_bit", (byte) 0).addByte("update_bit", (byte) 0).build(), + KnownBlockRepr.B_161_0_LEAVES2_ACACIA + ), + new Pair<>( + new BlockStateBuilder().addProperty("new_leaf_type", "dark_oak").addByte("persistent_bit", (byte) 0).addByte("update_bit", (byte) 0).build(), + KnownBlockRepr.B_161_1_LEAVES2_BIG_OAK + ) + }); + mMapTypeToBlocks.put("log2", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("new_log_type", "acacia").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_162_0_LOG2_ACACIA + ), + new Pair<>( + new BlockStateBuilder().addProperty("new_log_type", "dark_oak").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_162_1_LOG2_BIG_OAK + ) + }); + mMapTypeToBlocks.put("acacia_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_163_0_ACACIA_STAIRS + ) + }); + mMapTypeToBlocks.put("dark_oak_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_164_0_DARK_OAK_STAIRS + ) + }); + mMapTypeToBlocks.put("slime", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_165_0_SLIME + ) + }); + mMapTypeToBlocks.put("iron_trapdoor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_167_0_IRON_TRAPDOOR + ) + }); + mMapTypeToBlocks.put("prismarine", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("prismarine_block_type", "default").build(), + KnownBlockRepr.B_168_0_PRISMARINE_ROUGH + ), + new Pair<>( + new BlockStateBuilder().addProperty("prismarine_block_type", "dark").build(), + KnownBlockRepr.B_168_1_PRISMARINE_DARK + ), + new Pair<>( + new BlockStateBuilder().addProperty("prismarine_block_type", "bricks").build(), + KnownBlockRepr.B_168_2_PRISMARINE_BRICKS + ) + }); + mMapTypeToBlocks.put("seaLantern", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_169_0_SEALANTERN + ) + }); + mMapTypeToBlocks.put("hay_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("deprecated", 0).addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_170_0_HAY_BLOCK + ) + }); + mMapTypeToBlocks.put("carpet", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_171_0_CARPET_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_171_1_CARPET_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_171_2_CARPET_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_171_3_CARPET_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_171_4_CARPET_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_171_5_CARPET_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_171_6_CARPET_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_171_7_CARPET_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_171_8_CARPET_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_171_9_CARPET_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_171_10_CARPET_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_171_11_CARPET_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_171_12_CARPET_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_171_13_CARPET_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_171_14_CARPET_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_171_15_CARPET_BLACK + ) + }); + mMapTypeToBlocks.put("hardened_clay", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_172_0_HARDENED_CLAY + ) + }); + mMapTypeToBlocks.put("coal_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_173_0_COAL_BLOCK + ) + }); + mMapTypeToBlocks.put("packed_ice", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_174_0_PACKED_ICE + ) + }); + mMapTypeToBlocks.put("double_plant", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("double_plant_type", "sunflower").addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_175_0_DOUBLE_PLANT_SUNFLOWER + ), + new Pair<>( + new BlockStateBuilder().addProperty("double_plant_type", "syringa").addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_175_1_DOUBLE_PLANT_SYRINGA + ), + new Pair<>( + new BlockStateBuilder().addProperty("double_plant_type", "grass").addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_175_2_DOUBLE_PLANT_GRASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("double_plant_type", "fern").addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_175_3_DOUBLE_PLANT_FERN + ), + new Pair<>( + new BlockStateBuilder().addProperty("double_plant_type", "rose").addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_175_4_DOUBLE_PLANT_ROSE + ), + new Pair<>( + new BlockStateBuilder().addProperty("double_plant_type", "paeonia").addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_175_5_DOUBLE_PLANT_PAEONIA + ) + }); + mMapTypeToBlocks.put("banner", new Pair[]{ + + }); + mMapTypeToBlocks.put("daylight_detector_inverted", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_178_0_DAYLIGHT_DETECTOR_INVERTED + ) + }); + mMapTypeToBlocks.put("red_sandstone", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("sand_stone_type", "default").build(), + KnownBlockRepr.B_179_0_RED_SANDSTONE_DEFAULT + ), + new Pair<>( + new BlockStateBuilder().addProperty("sand_stone_type", "heiroglyphs").build(), + KnownBlockRepr.B_179_1_RED_SANDSTONE_CHISELED + ), + new Pair<>( + new BlockStateBuilder().addProperty("sand_stone_type", "cut").build(), + KnownBlockRepr.B_179_2_RED_SANDSTONE_SMOOTH + ) + }); + mMapTypeToBlocks.put("red_sandstone_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_180_0_RED_SANDSTONE_STAIRS + ) + }); + mMapTypeToBlocks.put("double_stone_slab2", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type_2", "red_sandstone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_181_0_DOUBLE_STONE_SLAB2_RED_SANDSTONE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type_2", "purpur").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_181_1_DOUBLE_STONE_SLAB2_PURPUR + ) + }); + mMapTypeToBlocks.put("stone_slab2", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type_2", "red_sandstone").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_182_0_STONE_SLAB2_RED_SANDSTONE + ), + new Pair<>( + new BlockStateBuilder().addProperty("stone_slab_type_2", "purpur").addByte("top_slot_bit", (byte) 0).build(), + KnownBlockRepr.B_182_1_STONE_SLAB2_PURPUR + ) + }); + mMapTypeToBlocks.put("spruce_fence_gate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("in_wall_bit", (byte) 0).addByte("open_bit", (byte) 0).build(), + KnownBlockRepr.B_183_0_SPRUCE_FENCE_GATE + ) + }); + mMapTypeToBlocks.put("birch_fence_gate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("in_wall_bit", (byte) 0).addByte("open_bit", (byte) 0).build(), + KnownBlockRepr.B_184_0_BIRCH_FENCE_GATE + ) + }); + mMapTypeToBlocks.put("jungle_fence_gate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("in_wall_bit", (byte) 0).addByte("open_bit", (byte) 0).build(), + KnownBlockRepr.B_185_0_JUNGLE_FENCE_GATE + ) + }); + mMapTypeToBlocks.put("dark_oak_fence_gate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("in_wall_bit", (byte) 0).addByte("open_bit", (byte) 0).build(), + KnownBlockRepr.B_186_0_DARK_OAK_FENCE_GATE + ) + }); + mMapTypeToBlocks.put("acacia_fence_gate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("in_wall_bit", (byte) 0).addByte("open_bit", (byte) 0).build(), + KnownBlockRepr.B_187_0_ACACIA_FENCE_GATE + ) + }); + mMapTypeToBlocks.put("repeating_command_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_0_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_1_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_2_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_3_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_4_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_5_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_6_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_188_7_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_8_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_9_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_10_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_11_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_12_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_13_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_14_REPEATING_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_188_15_REPEATING_COMMAND_BLOCK + ) + }); + mMapTypeToBlocks.put("chain_command_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_0_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_1_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_2_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_3_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_4_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_5_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_6_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 0).build(), + KnownBlockRepr.B_189_7_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_8_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_9_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_10_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_11_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_12_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_13_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_14_CHAIN_COMMAND_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("conditional_bit", (byte) 1).build(), + KnownBlockRepr.B_189_15_CHAIN_COMMAND_BLOCK + ) + }); + mMapTypeToBlocks.put("hard_glass_pane", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_190_0_HARD_GLASS_PANE + ) + }); + mMapTypeToBlocks.put("hard_stained_glass_pane", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_191_0_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_191_1_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_191_2_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_191_3_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_191_4_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_191_5_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_191_6_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_191_7_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_191_8_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_191_9_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_191_10_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_191_11_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_191_12_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_191_13_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_191_14_HARD_STAINED_GLASS_PANE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_191_15_HARD_STAINED_GLASS_PANE + ) + }); + mMapTypeToBlocks.put("chemical_heat", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_192_0_CHEMICAL_HEAT + ) + }); + mMapTypeToBlocks.put("spruce_door", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("door_hinge_bit", (byte) 0).addByte("open_bit", (byte) 0).addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_193_0_SPRUCE_DOOR + ) + }); + mMapTypeToBlocks.put("birch_door", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("door_hinge_bit", (byte) 0).addByte("open_bit", (byte) 0).addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_194_0_BIRCH_DOOR + ) + }); + mMapTypeToBlocks.put("jungle_door", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("door_hinge_bit", (byte) 0).addByte("open_bit", (byte) 0).addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_195_0_JUNGLE_DOOR + ) + }); + mMapTypeToBlocks.put("acacia_door", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("door_hinge_bit", (byte) 0).addByte("open_bit", (byte) 0).addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_196_0_ACACIA_DOOR + ) + }); + mMapTypeToBlocks.put("dark_oak_door", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("door_hinge_bit", (byte) 0).addByte("open_bit", (byte) 0).addByte("upper_block_bit", (byte) 0).build(), + KnownBlockRepr.B_197_0_DARK_OAK_DOOR + ) + }); + mMapTypeToBlocks.put("grass_path", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_198_0_GRASS_PATH + ) + }); + mMapTypeToBlocks.put("frame", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("item_frame_map_bit", (byte) 0).build(), + KnownBlockRepr.B_199_0_FRAME + ) + }); + mMapTypeToBlocks.put("chorus_flower", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("age", 0).build(), + KnownBlockRepr.B_200_0_CHORUS_FLOWER + ) + }); + mMapTypeToBlocks.put("purpur_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "default").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_201_0_PURPUR_BLOCK_DEFAULT + ), + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "chiseled").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_201_1_PURPUR_BLOCK_CHISELED + ), + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "lines").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_201_2_PURPUR_BLOCK_LINES + ), + new Pair<>( + new BlockStateBuilder().addProperty("chisel_type", "smooth").addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_201_3_PURPUR_BLOCK_DEFAULT + ) + }); + mMapTypeToBlocks.put("purpur_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_203_0_PURPUR_STAIRS + ) + }); + mMapTypeToBlocks.put("shulker_box", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_205_0_SHULKERBOX + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_218_0_SHULKERBOX_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_218_1_SHULKERBOX_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_218_2_SHULKERBOX_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_218_3_SHULKERBOX_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_218_4_SHULKERBOX_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_218_5_SHULKERBOX_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_218_6_SHULKERBOX_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_218_7_SHULKERBOX_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_218_8_SHULKERBOX_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_218_9_SHULKERBOX_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_218_10_SHULKERBOX_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_218_11_SHULKERBOX_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_218_12_SHULKERBOX_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_218_13_SHULKERBOX_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_218_14_SHULKERBOX_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_218_15_SHULKERBOX_BLACK + ) + }); + mMapTypeToBlocks.put("end_bricks", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_206_0_END_BRICKS + ) + }); + mMapTypeToBlocks.put("end_rod", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).build(), + KnownBlockRepr.B_208_0_END_ROD + ) + }); + mMapTypeToBlocks.put("end_gateway", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_209_0_END_GATEWAY + ) + }); + mMapTypeToBlocks.put("210", new Pair[]{ + + }); + mMapTypeToBlocks.put("211", new Pair[]{ + + }); + mMapTypeToBlocks.put("212", new Pair[]{ + + }); + mMapTypeToBlocks.put("magma", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_213_0_MAGMA_BLOCK + ) + }); + mMapTypeToBlocks.put("nether_wart_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_214_0_NETHERWART_BLOCK + ) + }); + mMapTypeToBlocks.put("red_nether_brick", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_215_0_RED_NETHER_BRICK + ) + }); + mMapTypeToBlocks.put("bone_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("deprecated", 0).addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_216_0_BONE + ) + }); + mMapTypeToBlocks.put("purple_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_219_2_GLAZED_TERRACOTTA_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_219_3_GLAZED_TERRACOTTA_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_219_4_GLAZED_TERRACOTTA_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_219_5_GLAZED_TERRACOTTA_PURPLE + ) + }); + mMapTypeToBlocks.put("white_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_220_2_GLAZED_TERRACOTTA_WHITE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_220_3_GLAZED_TERRACOTTA_WHITE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_220_4_GLAZED_TERRACOTTA_WHITE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_220_5_GLAZED_TERRACOTTA_WHITE + ) + }); + mMapTypeToBlocks.put("orange_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_221_2_GLAZED_TERRACOTTA_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_221_3_GLAZED_TERRACOTTA_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_221_4_GLAZED_TERRACOTTA_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_221_5_GLAZED_TERRACOTTA_ORANGE + ) + }); + mMapTypeToBlocks.put("magenta_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_222_2_GLAZED_TERRACOTTA_LIGHT_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_222_3_GLAZED_TERRACOTTA_LIGHT_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_222_4_GLAZED_TERRACOTTA_LIGHT_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_222_5_GLAZED_TERRACOTTA_LIGHT_MAGENTA + ) + }); + mMapTypeToBlocks.put("light_blue_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_223_2_GLAZED_TERRACOTTA_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_223_3_GLAZED_TERRACOTTA_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_223_4_GLAZED_TERRACOTTA_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_223_5_GLAZED_TERRACOTTA_LIGHT_BLUE + ) + }); + mMapTypeToBlocks.put("yellow_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_224_2_GLAZED_TERRACOTTA_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_224_3_GLAZED_TERRACOTTA_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_224_4_GLAZED_TERRACOTTA_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_224_5_GLAZED_TERRACOTTA_YELLOW + ) + }); + mMapTypeToBlocks.put("lime_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_225_2_GLAZED_TERRACOTTA_LIME + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_225_3_GLAZED_TERRACOTTA_LIME + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_225_4_GLAZED_TERRACOTTA_LIME + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_225_5_GLAZED_TERRACOTTA_LIME + ) + }); + mMapTypeToBlocks.put("pink_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_226_2_GLAZED_TERRACOTTA_PINK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_226_3_GLAZED_TERRACOTTA_PINK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_226_4_GLAZED_TERRACOTTA_PINK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_226_5_GLAZED_TERRACOTTA_PINK + ) + }); + mMapTypeToBlocks.put("gray_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_227_2_GLAZED_TERRACOTTA_GRAY + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_227_3_GLAZED_TERRACOTTA_GRAY + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_227_4_GLAZED_TERRACOTTA_GRAY + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_227_5_GLAZED_TERRACOTTA_GRAY + ) + }); + mMapTypeToBlocks.put("silver_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_228_2_GLAZED_TERRACOTTA_LIGHT_GRAY + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_228_3_GLAZED_TERRACOTTA_LIGHT_GRAY + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_228_4_GLAZED_TERRACOTTA_LIGHT_GRAY + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_228_5_GLAZED_TERRACOTTA_LIGHT_GRAY + ) + }); + mMapTypeToBlocks.put("cyan_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_229_2_GLAZED_TERRACOTTA_CYAN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_229_3_GLAZED_TERRACOTTA_CYAN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_229_4_GLAZED_TERRACOTTA_CYAN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_229_5_GLAZED_TERRACOTTA_CYAN + ) + }); + mMapTypeToBlocks.put("230", new Pair[]{ + + }); + mMapTypeToBlocks.put("blue_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_231_2_GLAZED_TERRACOTTA_BLUE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_231_3_GLAZED_TERRACOTTA_BLUE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_231_4_GLAZED_TERRACOTTA_BLUE + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_231_5_GLAZED_TERRACOTTA_BLUE + ) + }); + mMapTypeToBlocks.put("brown_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_232_2_GLAZED_TERRACOTTA_BROWN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_232_3_GLAZED_TERRACOTTA_BROWN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_232_4_GLAZED_TERRACOTTA_BROWN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_232_5_GLAZED_TERRACOTTA_BROWN + ) + }); + mMapTypeToBlocks.put("green_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_233_2_GLAZED_TERRACOTTA_GREEN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_233_3_GLAZED_TERRACOTTA_GREEN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_233_4_GLAZED_TERRACOTTA_GREEN + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_233_5_GLAZED_TERRACOTTA_GREEN + ) + }); + mMapTypeToBlocks.put("red_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_234_2_GLAZED_TERRACOTTA_RED + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_234_3_GLAZED_TERRACOTTA_RED + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_234_4_GLAZED_TERRACOTTA_RED + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_234_5_GLAZED_TERRACOTTA_RED + ) + }); + mMapTypeToBlocks.put("black_glazed_terracotta", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).build(), + KnownBlockRepr.B_235_2_GLAZED_TERRACOTTA_BLACK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).build(), + KnownBlockRepr.B_235_3_GLAZED_TERRACOTTA_BLACK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).build(), + KnownBlockRepr.B_235_4_GLAZED_TERRACOTTA_BLACK + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).build(), + KnownBlockRepr.B_235_5_GLAZED_TERRACOTTA_BLACK + ) + }); + mMapTypeToBlocks.put("concrete", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_236_0_CONCRETE_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_236_1_CONCRETE_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_236_2_CONCRETE_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_236_3_CONCRETE_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_236_4_CONCRETE_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_236_5_CONCRETE_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_236_6_CONCRETE_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_236_7_CONCRETE_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_236_8_CONCRETE_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_236_9_CONCRETE_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_236_10_CONCRETE_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_236_11_CONCRETE_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_236_12_CONCRETE_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_236_13_CONCRETE_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_236_14_CONCRETE_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_236_15_CONCRETE_BLACK + ) + }); + mMapTypeToBlocks.put("concretePowder", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_237_0_CONCRETE_POWDER_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_237_1_CONCRETE_POWDER_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_237_2_CONCRETE_POWDER_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_237_3_CONCRETE_POWDER_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_237_4_CONCRETE_POWDER_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_237_5_CONCRETE_POWDER_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_237_6_CONCRETE_POWDER_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_237_7_CONCRETE_POWDER_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_237_8_CONCRETE_POWDER_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_237_9_CONCRETE_POWDER_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_237_10_CONCRETE_POWDER_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_237_11_CONCRETE_POWDER_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_237_12_CONCRETE_POWDER_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_237_13_CONCRETE_POWDER_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_237_14_CONCRETE_POWDER_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_237_15_CONCRETE_POWDER_BLACK + ) + }); + mMapTypeToBlocks.put("chemistry_table", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "compound_creator").addInt("direction", 0).build(), + KnownBlockRepr.B_238_0_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "compound_creator").addInt("direction", 1).build(), + KnownBlockRepr.B_238_1_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "compound_creator").addInt("direction", 2).build(), + KnownBlockRepr.B_238_2_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "compound_creator").addInt("direction", 3).build(), + KnownBlockRepr.B_238_3_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "material_reducer").addInt("direction", 0).build(), + KnownBlockRepr.B_238_4_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "material_reducer").addInt("direction", 1).build(), + KnownBlockRepr.B_238_5_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "material_reducer").addInt("direction", 2).build(), + KnownBlockRepr.B_238_6_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "material_reducer").addInt("direction", 3).build(), + KnownBlockRepr.B_238_7_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "element_constructor").addInt("direction", 0).build(), + KnownBlockRepr.B_238_8_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "element_constructor").addInt("direction", 1).build(), + KnownBlockRepr.B_238_9_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "element_constructor").addInt("direction", 2).build(), + KnownBlockRepr.B_238_10_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "element_constructor").addInt("direction", 3).build(), + KnownBlockRepr.B_238_11_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "lab_table").addInt("direction", 0).build(), + KnownBlockRepr.B_238_12_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "lab_table").addInt("direction", 1).build(), + KnownBlockRepr.B_238_13_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "lab_table").addInt("direction", 2).build(), + KnownBlockRepr.B_238_14_CHEMISTRY_TABLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("chemistry_table_type", "lab_table").addInt("direction", 3).build(), + KnownBlockRepr.B_238_15_CHEMISTRY_TABLE + ) + }); + mMapTypeToBlocks.put("underwater_torch", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "unknown").build(), + KnownBlockRepr.B_239_0_UNDERWATER_TORCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "west").build(), + KnownBlockRepr.B_239_1_UNDERWATER_TORCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "east").build(), + KnownBlockRepr.B_239_2_UNDERWATER_TORCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "north").build(), + KnownBlockRepr.B_239_3_UNDERWATER_TORCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "south").build(), + KnownBlockRepr.B_239_4_UNDERWATER_TORCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "top").build(), + KnownBlockRepr.B_239_5_UNDERWATER_TORCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "unknown").build(), + KnownBlockRepr.B_239_6_UNDERWATER_TORCH + ), + new Pair<>( + new BlockStateBuilder().addProperty("torch_facing_direction", "unknown").build(), + KnownBlockRepr.B_239_7_UNDERWATER_TORCH + ) + }); + mMapTypeToBlocks.put("chorus_plant", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_240_0_CHORUS_PLANT + ) + }); + mMapTypeToBlocks.put("stained_glass", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_241_0_STAINED_GLASS_WHITE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_241_1_STAINED_GLASS_ORANGE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_241_2_STAINED_GLASS_MAGENTA + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_241_3_STAINED_GLASS_LIGHT_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_241_4_STAINED_GLASS_YELLOW + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_241_5_STAINED_GLASS_LIME + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_241_6_STAINED_GLASS_PINK + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_241_7_STAINED_GLASS_GRAY + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_241_8_STAINED_GLASS_SILVER + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_241_9_STAINED_GLASS_CYAN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_241_10_STAINED_GLASS_PURPLE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_241_11_STAINED_GLASS_BLUE + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_241_12_STAINED_GLASS_BROWN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_241_13_STAINED_GLASS_GREEN + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_241_14_STAINED_GLASS_RED + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_241_15_STAINED_GLASS_BLACK + ) + }); + mMapTypeToBlocks.put("242", new Pair[]{ + + }); + mMapTypeToBlocks.put("podzol", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_243_0_PODZOL + ) + }); + mMapTypeToBlocks.put("beetroot", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("growth", 0).build(), + KnownBlockRepr.B_244_0_BEETROOT + ) + }); + mMapTypeToBlocks.put("stonecutter", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_245_0_STONECUTTER + ) + }); + mMapTypeToBlocks.put("glowingobsidian", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_246_0_GLOWINGOBSIDIAN + ) + }); + mMapTypeToBlocks.put("netherreactor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_247_0_NETHERREACTOR_DEFAULT + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_247_1_NETHERREACTOR_ACTIVE + ), + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_247_2_NETHERREACTOR_COOLED + ) + }); + mMapTypeToBlocks.put("info_update", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_248_0_INFO_UPDATE + ) + }); + mMapTypeToBlocks.put("info_update2", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_249_0_INFO_UPDATE2 + ) + }); + mMapTypeToBlocks.put("movingBlock", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_250_0_MOVINGBLOCK + ) + }); + mMapTypeToBlocks.put("observer", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_0_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_1_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_2_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_3_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_4_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_5_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_6_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("powered_bit", (byte) 0).build(), + KnownBlockRepr.B_251_7_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_8_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_9_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_10_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_11_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_12_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_13_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_14_OBSERVER + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("powered_bit", (byte) 1).build(), + KnownBlockRepr.B_251_15_OBSERVER + ) + }); + mMapTypeToBlocks.put("structure_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "data").build(), + KnownBlockRepr.B_252_0_STRUCTURE_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "save").build(), + KnownBlockRepr.B_252_1_STRUCTURE_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "load").build(), + KnownBlockRepr.B_252_2_STRUCTURE_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "corner").build(), + KnownBlockRepr.B_252_3_STRUCTURE_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "invalid").build(), + KnownBlockRepr.B_252_4_STRUCTURE_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "export").build(), + KnownBlockRepr.B_252_5_STRUCTURE_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "data").build(), + KnownBlockRepr.B_252_6_STRUCTURE_BLOCK + ), + new Pair<>( + new BlockStateBuilder().addProperty("structure_block_type", "data").build(), + KnownBlockRepr.B_252_7_STRUCTURE_BLOCK + ) + }); + mMapTypeToBlocks.put("hard_glass", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_253_0_HARD_GLASS + ) + }); + mMapTypeToBlocks.put("hard_stained_glass", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("color", "white").build(), + KnownBlockRepr.B_254_0_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "orange").build(), + KnownBlockRepr.B_254_1_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "magenta").build(), + KnownBlockRepr.B_254_2_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "light_blue").build(), + KnownBlockRepr.B_254_3_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "yellow").build(), + KnownBlockRepr.B_254_4_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "lime").build(), + KnownBlockRepr.B_254_5_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "pink").build(), + KnownBlockRepr.B_254_6_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "gray").build(), + KnownBlockRepr.B_254_7_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "silver").build(), + KnownBlockRepr.B_254_8_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "cyan").build(), + KnownBlockRepr.B_254_9_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "purple").build(), + KnownBlockRepr.B_254_10_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "blue").build(), + KnownBlockRepr.B_254_11_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "brown").build(), + KnownBlockRepr.B_254_12_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "green").build(), + KnownBlockRepr.B_254_13_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "red").build(), + KnownBlockRepr.B_254_14_HARD_STAINED_GLASS + ), + new Pair<>( + new BlockStateBuilder().addProperty("color", "black").build(), + KnownBlockRepr.B_254_15_HARD_STAINED_GLASS + ) + }); + mMapTypeToBlocks.put("reserved6", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_255_0_RESERVED6 + ) + }); + mMapTypeToBlocks.put("256", new Pair[]{ + + }); + mMapTypeToBlocks.put("prismarine_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2154_0_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2155_1_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 2).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2156_2_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 3).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2157_3_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2158_4_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2159_5_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 2).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2160_6_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 3).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2161_7_prismarine_stairs + ) + }); + mMapTypeToBlocks.put("dark_prismarine_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2162_0_dark_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2163_1_dark_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 2).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2164_2_dark_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 3).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2165_3_dark_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2166_4_dark_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2167_5_dark_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 2).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2168_6_dark_prismarine_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 3).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2169_7_dark_prismarine_stairs + ) + }); + mMapTypeToBlocks.put("prismarine_bricks_stairs", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2170_0_prismarine_bricks_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2171_1_prismarine_bricks_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 2).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2172_2_prismarine_bricks_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 3).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_2173_3_prismarine_bricks_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2174_4_prismarine_bricks_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2175_5_prismarine_bricks_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 2).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2176_6_prismarine_bricks_stairs + ), + new Pair<>( + new BlockStateBuilder().addInt("weirdo_direction", 3).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_2177_7_prismarine_bricks_stairs + ) + }); + mMapTypeToBlocks.put("stripped_spruce_log", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2178_0_stripped_spruce_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "x").build(), + KnownBlockRepr.B_2179_1_stripped_spruce_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "z").build(), + KnownBlockRepr.B_2180_2_stripped_spruce_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2181_3_stripped_spruce_log + ) + }); + mMapTypeToBlocks.put("stripped_birch_log", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2182_0_stripped_birch_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "x").build(), + KnownBlockRepr.B_2183_1_stripped_birch_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "z").build(), + KnownBlockRepr.B_2184_2_stripped_birch_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2185_3_stripped_birch_log + ) + }); + mMapTypeToBlocks.put("stripped_jungle_log", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2186_0_stripped_jungle_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "x").build(), + KnownBlockRepr.B_2187_1_stripped_jungle_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "z").build(), + KnownBlockRepr.B_2188_2_stripped_jungle_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2189_3_stripped_jungle_log + ) + }); + mMapTypeToBlocks.put("stripped_acacia_log", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2190_0_stripped_acacia_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "x").build(), + KnownBlockRepr.B_2191_1_stripped_acacia_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "z").build(), + KnownBlockRepr.B_2192_2_stripped_acacia_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2193_3_stripped_acacia_log + ) + }); + mMapTypeToBlocks.put("stripped_dark_oak_log", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2194_0_stripped_dark_oak_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "x").build(), + KnownBlockRepr.B_2195_1_stripped_dark_oak_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "z").build(), + KnownBlockRepr.B_2196_2_stripped_dark_oak_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2197_3_stripped_dark_oak_log + ) + }); + mMapTypeToBlocks.put("stripped_oak_log", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2198_0_stripped_oak_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "x").build(), + KnownBlockRepr.B_2199_1_stripped_oak_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "z").build(), + KnownBlockRepr.B_2200_2_stripped_oak_log + ), + new Pair<>( + new BlockStateBuilder().addProperty("pillar_axis", "y").build(), + KnownBlockRepr.B_2201_3_stripped_oak_log + ) + }); + mMapTypeToBlocks.put("blue_ice", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_2202_0_blue_ice + ) + }); + mMapTypeToBlocks.put("seagrass", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("sea_grass_type", "default").build(), + KnownBlockRepr.B_4091_0_seagrass + ), + new Pair<>( + new BlockStateBuilder().addProperty("sea_grass_type", "double_top").build(), + KnownBlockRepr.B_4092_1_seagrass + ), + new Pair<>( + new BlockStateBuilder().addProperty("sea_grass_type", "double_bot").build(), + KnownBlockRepr.B_4093_2_seagrass + ), + new Pair<>( + new BlockStateBuilder().addProperty("sea_grass_type", "default").build(), + KnownBlockRepr.B_4094_3_seagrass + ) + }); + mMapTypeToBlocks.put("coral", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4095_0_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4096_1_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "purple").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4097_2_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "red").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4098_3_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4099_4_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4100_5_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4101_6_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4102_7_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4103_8_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4104_9_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "purple").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4105_10_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "red").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4106_11_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4107_12_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4108_13_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4109_14_coral + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4110_15_coral + ) + }); + mMapTypeToBlocks.put("coral_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4111_0_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4112_1_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "purple").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4113_2_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "red").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4114_3_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4115_4_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4116_5_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4117_6_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4118_7_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4119_8_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4120_9_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "purple").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4121_10_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "red").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4122_11_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4123_12_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4124_13_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4125_14_coral_block + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4126_15_coral_block + ) + }); + mMapTypeToBlocks.put("coral_fan", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4128_1_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4131_4_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4132_5_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4133_6_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4135_8_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4136_9_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "purple").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4137_10_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "red").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4138_11_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4139_12_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4140_13_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4141_14_coral_fan + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4142_15_coral_fan + ) + }); + mMapTypeToBlocks.put("coral_fan_dead", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4143_0_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4144_1_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "purple").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4145_2_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "red").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4146_3_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4147_4_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4148_5_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4149_6_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4150_7_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4151_8_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "pink").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4152_9_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "purple").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4153_10_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "red").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4154_11_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "yellow").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4155_12_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4156_13_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 1).build(), + KnownBlockRepr.B_4157_14_coral_fan_dead + ), + new Pair<>( + new BlockStateBuilder().addProperty("coral_color", "blue").addInt("coral_fan_direction", 0).build(), + KnownBlockRepr.B_4158_15_coral_fan_dead + ) + }); + mMapTypeToBlocks.put("coral_fan_hang", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 0).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4159_0_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 0).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4160_1_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 0).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4161_2_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 0).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4162_3_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 1).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4163_4_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 1).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4164_5_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 1).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4165_6_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 2).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4167_8_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 2).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4168_9_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 2).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4170_11_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 3).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4171_12_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 3).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4172_13_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 3).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4173_14_coral_fan_hang + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 3).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4174_15_coral_fan_hang + ) + }); + mMapTypeToBlocks.put("coral_fan_hang2", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 0).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4177_2_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 1).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4180_5_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 1).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4181_6_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 1).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4182_7_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 2).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4183_8_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 2).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4184_9_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 2).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4185_10_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 2).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4186_11_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 3).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4189_14_coral_fan_hang2 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 3).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4190_15_coral_fan_hang2 + ) + }); + mMapTypeToBlocks.put("coral_fan_hang3", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 0).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4191_0_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 0).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4193_2_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 0).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4194_3_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 1).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4195_4_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 1).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4196_5_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 1).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4197_6_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 1).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4198_7_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 2).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4199_8_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 2).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4200_9_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 2).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4201_10_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 2).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4202_11_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 3).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4203_12_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 3).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4204_13_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 0).addInt("coral_direction", 3).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4205_14_coral_fan_hang3 + ), + new Pair<>( + new BlockStateBuilder().addByte("coral_hang_type_bit", (byte) 1).addInt("coral_direction", 3).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4206_15_coral_fan_hang3 + ) + }); + mMapTypeToBlocks.put("kelp", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 0).build(), + KnownBlockRepr.B_4207_0_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 1).build(), + KnownBlockRepr.B_4208_1_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 2).build(), + KnownBlockRepr.B_4209_2_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 3).build(), + KnownBlockRepr.B_4210_3_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 4).build(), + KnownBlockRepr.B_4211_4_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 5).build(), + KnownBlockRepr.B_4212_5_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 6).build(), + KnownBlockRepr.B_4213_6_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 7).build(), + KnownBlockRepr.B_4214_7_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 8).build(), + KnownBlockRepr.B_4215_8_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 9).build(), + KnownBlockRepr.B_4216_9_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 10).build(), + KnownBlockRepr.B_4217_10_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 11).build(), + KnownBlockRepr.B_4218_11_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 12).build(), + KnownBlockRepr.B_4219_12_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 13).build(), + KnownBlockRepr.B_4220_13_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 14).build(), + KnownBlockRepr.B_4221_14_kelp + ), + new Pair<>( + new BlockStateBuilder().addInt("kelp_age", 15).build(), + KnownBlockRepr.B_4222_15_kelp + ) + }); + mMapTypeToBlocks.put("dried_kelp_block", new Pair[]{ + new Pair<>( + new BlockStateBuilder().build(), + KnownBlockRepr.B_4223_0_dried_kelp_block + ) + }); + mMapTypeToBlocks.put("acacia_button", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4224_0_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4225_1_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4226_2_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4227_3_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4228_4_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4229_5_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4230_6_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4231_7_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4232_8_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4233_9_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4234_10_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4235_11_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4236_12_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4237_13_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4238_14_acacia_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4239_15_acacia_button + ) + }); + mMapTypeToBlocks.put("birch_button", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4240_0_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4241_1_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4242_2_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4243_3_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4244_4_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4245_5_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4246_6_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4247_7_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4248_8_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4249_9_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4250_10_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4251_11_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4252_12_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4253_13_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4254_14_birch_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4255_15_birch_button + ) + }); + mMapTypeToBlocks.put("dark_oak_button", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4256_0_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4257_1_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4258_2_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4259_3_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4260_4_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4261_5_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4262_6_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4263_7_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4264_8_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4265_9_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4266_10_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4267_11_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4268_12_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4269_13_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4270_14_dark_oak_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4271_15_dark_oak_button + ) + }); + mMapTypeToBlocks.put("jungle_button", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4272_0_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4273_1_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4274_2_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4275_3_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4276_4_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4277_5_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4278_6_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4279_7_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4280_8_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4281_9_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4282_10_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4283_11_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4284_12_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4285_13_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4286_14_jungle_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4287_15_jungle_button + ) + }); + mMapTypeToBlocks.put("spruce_button", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4288_0_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4289_1_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4290_2_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4291_3_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4292_4_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4293_5_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4294_6_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 0).build(), + KnownBlockRepr.B_4295_7_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4296_8_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 1).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4297_9_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 2).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4298_10_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 3).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4299_11_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 4).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4300_12_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 5).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4301_13_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4302_14_spruce_button + ), + new Pair<>( + new BlockStateBuilder().addInt("facing_direction", 0).addByte("button_pressed_bit", (byte) 1).build(), + KnownBlockRepr.B_4303_15_spruce_button + ) + }); + mMapTypeToBlocks.put("acacia_trapdoor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4304_0_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4305_1_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4306_2_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4307_3_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4308_4_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4309_5_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4310_6_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4311_7_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4312_8_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4313_9_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4314_10_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4315_11_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4316_12_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4317_13_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4318_14_acacia_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4319_15_acacia_trapdoor + ) + }); + mMapTypeToBlocks.put("birch_trapdoor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4320_0_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4321_1_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4322_2_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4323_3_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4324_4_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4325_5_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4326_6_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4327_7_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4328_8_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4329_9_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4330_10_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4331_11_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4332_12_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4333_13_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4334_14_birch_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4335_15_birch_trapdoor + ) + }); + mMapTypeToBlocks.put("dark_oak_trapdoor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4336_0_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4337_1_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4338_2_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4339_3_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4340_4_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4341_5_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4342_6_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4343_7_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4344_8_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4345_9_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4346_10_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4347_11_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4348_12_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4349_13_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4350_14_dark_oak_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4351_15_dark_oak_trapdoor + ) + }); + mMapTypeToBlocks.put("jungle_trapdoor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4352_0_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4353_1_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4354_2_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4355_3_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4356_4_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4357_5_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4358_6_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4359_7_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4360_8_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4361_9_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4362_10_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4363_11_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4364_12_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4365_13_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4366_14_jungle_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4367_15_jungle_trapdoor + ) + }); + mMapTypeToBlocks.put("spruce_trapdoor", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4368_0_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4369_1_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4370_2_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4371_3_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4372_4_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4373_5_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4374_6_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 0).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4375_7_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4376_8_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4377_9_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4378_10_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 0).build(), + KnownBlockRepr.B_4379_11_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4380_12_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4381_13_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4382_14_spruce_trapdoor + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).addByte("open_bit", (byte) 1).addByte("upside_down_bit", (byte) 1).build(), + KnownBlockRepr.B_4383_15_spruce_trapdoor + ) + }); + mMapTypeToBlocks.put("acacia_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_4384_0_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 1).build(), + KnownBlockRepr.B_4385_1_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 2).build(), + KnownBlockRepr.B_4386_2_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 3).build(), + KnownBlockRepr.B_4387_3_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 4).build(), + KnownBlockRepr.B_4388_4_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 5).build(), + KnownBlockRepr.B_4389_5_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 6).build(), + KnownBlockRepr.B_4390_6_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 7).build(), + KnownBlockRepr.B_4391_7_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 8).build(), + KnownBlockRepr.B_4392_8_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 9).build(), + KnownBlockRepr.B_4393_9_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 10).build(), + KnownBlockRepr.B_4394_10_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 11).build(), + KnownBlockRepr.B_4395_11_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 12).build(), + KnownBlockRepr.B_4396_12_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 13).build(), + KnownBlockRepr.B_4397_13_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 14).build(), + KnownBlockRepr.B_4398_14_acacia_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 15).build(), + KnownBlockRepr.B_4399_15_acacia_pressure_plate + ) + }); + mMapTypeToBlocks.put("birch_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_4400_0_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 1).build(), + KnownBlockRepr.B_4401_1_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 2).build(), + KnownBlockRepr.B_4402_2_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 3).build(), + KnownBlockRepr.B_4403_3_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 4).build(), + KnownBlockRepr.B_4404_4_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 5).build(), + KnownBlockRepr.B_4405_5_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 6).build(), + KnownBlockRepr.B_4406_6_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 7).build(), + KnownBlockRepr.B_4407_7_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 8).build(), + KnownBlockRepr.B_4408_8_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 9).build(), + KnownBlockRepr.B_4409_9_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 10).build(), + KnownBlockRepr.B_4410_10_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 11).build(), + KnownBlockRepr.B_4411_11_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 12).build(), + KnownBlockRepr.B_4412_12_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 13).build(), + KnownBlockRepr.B_4413_13_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 14).build(), + KnownBlockRepr.B_4414_14_birch_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 15).build(), + KnownBlockRepr.B_4415_15_birch_pressure_plate + ) + }); + mMapTypeToBlocks.put("dark_oak_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_4416_0_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 1).build(), + KnownBlockRepr.B_4417_1_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 2).build(), + KnownBlockRepr.B_4418_2_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 3).build(), + KnownBlockRepr.B_4419_3_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 4).build(), + KnownBlockRepr.B_4420_4_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 5).build(), + KnownBlockRepr.B_4421_5_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 6).build(), + KnownBlockRepr.B_4422_6_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 7).build(), + KnownBlockRepr.B_4423_7_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 8).build(), + KnownBlockRepr.B_4424_8_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 9).build(), + KnownBlockRepr.B_4425_9_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 10).build(), + KnownBlockRepr.B_4426_10_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 11).build(), + KnownBlockRepr.B_4427_11_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 12).build(), + KnownBlockRepr.B_4428_12_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 13).build(), + KnownBlockRepr.B_4429_13_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 14).build(), + KnownBlockRepr.B_4430_14_dark_oak_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 15).build(), + KnownBlockRepr.B_4431_15_dark_oak_pressure_plate + ) + }); + mMapTypeToBlocks.put("jungle_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_4432_0_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 1).build(), + KnownBlockRepr.B_4433_1_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 2).build(), + KnownBlockRepr.B_4434_2_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 3).build(), + KnownBlockRepr.B_4435_3_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 4).build(), + KnownBlockRepr.B_4436_4_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 5).build(), + KnownBlockRepr.B_4437_5_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 6).build(), + KnownBlockRepr.B_4438_6_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 7).build(), + KnownBlockRepr.B_4439_7_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 8).build(), + KnownBlockRepr.B_4440_8_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 9).build(), + KnownBlockRepr.B_4441_9_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 10).build(), + KnownBlockRepr.B_4442_10_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 11).build(), + KnownBlockRepr.B_4443_11_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 12).build(), + KnownBlockRepr.B_4444_12_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 13).build(), + KnownBlockRepr.B_4445_13_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 14).build(), + KnownBlockRepr.B_4446_14_jungle_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 15).build(), + KnownBlockRepr.B_4447_15_jungle_pressure_plate + ) + }); + mMapTypeToBlocks.put("spruce_pressure_plate", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 0).build(), + KnownBlockRepr.B_4448_0_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 1).build(), + KnownBlockRepr.B_4449_1_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 2).build(), + KnownBlockRepr.B_4450_2_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 3).build(), + KnownBlockRepr.B_4451_3_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 4).build(), + KnownBlockRepr.B_4452_4_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 5).build(), + KnownBlockRepr.B_4453_5_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 6).build(), + KnownBlockRepr.B_4454_6_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 7).build(), + KnownBlockRepr.B_4455_7_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 8).build(), + KnownBlockRepr.B_4456_8_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 9).build(), + KnownBlockRepr.B_4457_9_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 10).build(), + KnownBlockRepr.B_4458_10_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 11).build(), + KnownBlockRepr.B_4459_11_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 12).build(), + KnownBlockRepr.B_4460_12_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 13).build(), + KnownBlockRepr.B_4461_13_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 14).build(), + KnownBlockRepr.B_4462_14_spruce_pressure_plate + ), + new Pair<>( + new BlockStateBuilder().addInt("redstone_signal", 15).build(), + KnownBlockRepr.B_4463_15_spruce_pressure_plate + ) + }); + mMapTypeToBlocks.put("carved_pumpkin", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("direction", 0).build(), + KnownBlockRepr.B_4464_0_carved_pumpkin + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 1).build(), + KnownBlockRepr.B_4465_1_carved_pumpkin + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 2).build(), + KnownBlockRepr.B_4466_2_carved_pumpkin + ), + new Pair<>( + new BlockStateBuilder().addInt("direction", 3).build(), + KnownBlockRepr.B_4467_3_carved_pumpkin + ) + }); + mMapTypeToBlocks.put("sea_pickle", new Pair[]{ + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 0).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4468_0_sea_pickle + ), + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 1).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4469_1_sea_pickle + ), + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 2).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4470_2_sea_pickle + ), + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 3).addByte("dead_bit", (byte) 0).build(), + KnownBlockRepr.B_4471_3_sea_pickle + ), + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 0).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4472_4_sea_pickle + ), + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 1).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4473_5_sea_pickle + ), + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 2).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4474_6_sea_pickle + ), + new Pair<>( + new BlockStateBuilder().addInt("cluster_count", 3).addByte("dead_bit", (byte) 1).build(), + KnownBlockRepr.B_4475_7_sea_pickle + ) + }); + + } + + @Nullable + public static KnownBlockRepr getBestRepr(@NonNull OldBlock oldBlock) { + Pair[] list = mMapTypeToBlocks.get(oldBlock.getBlockType()); + if (list == null || list.length <= 0) + // Already the best we can d for now. + return null; + String[] checks = new String[]{"color", "type", "direction"}; + ArrayList tags = oldBlock.getStates().getValue(); + List> range = new ArrayList<>(list.length); + range.addAll(Arrays.asList(list)); + for (String check : checks) { + List> rangeNew = new ArrayList<>(range.size()); + for (Tag tag : tags) { + if (tag.getName().contains(check)) { + for (Pair pair : range) { + if (tag.equals(pair.first)) { + rangeNew.add(pair); + break; + } + } + } + } + if (rangeNew.size() > 0) range = rangeNew; + } + return range.get(0).second; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/KnownBlockRepr.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/KnownBlockRepr.java new file mode 100644 index 00000000..d3cfd5e0 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/KnownBlockRepr.java @@ -0,0 +1,1294 @@ +package com.mithrilmania.blocktopograph.block; + +import android.content.res.AssetManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.SparseArray; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; +import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by mithrilmania + *

+ * ========================== + * POCKET EDITION BLOCKS ONLY + * ========================== + *

+ * uvs are up to date with MCPE 0.14.0 + *

+ * --- Please attribute @mithrilmania for generating+updating this enum + */ +public enum KnownBlockRepr implements NamedBitmapProviderHandle, NamedBitmapProvider { + /* + * ============================== + * Blocks + * ============================== + */ + + + B_0_0_AIR("minecraft:air", null, 0, 0, null, 0x00000000, false), + B_1_0_STONE("minecraft:stone", "stone", 1, 0, "blocks/stone.png", 0xff464646, false), + B_1_1_STONE_GRANITE("minecraft:stone", "granite", 1, 1, "blocks/stone_granite.png", 0xff8c7167, false), + B_1_2_STONE_GRANITE_SMOOTH("minecraft:stone", "granite_smooth", 1, 2, "blocks/stone_granite_smooth.png", 0xff946251, false), + B_1_3_STONE_DIORITE("minecraft:stone", "diorite", 1, 3, "blocks/stone_diorite.png", 0xffc6c6c6, false), + B_1_4_STONE_DIORITE_SMOOTH("minecraft:stone", "diorite_smooth", 1, 4, "blocks/stone_diorite_smooth.png", 0xffbebec1, false), + B_1_5_STONE_ANDESITE("minecraft:stone", "andesite", 1, 5, "blocks/stone_andesite.png", 0xff797777, false), + B_1_6_STONE_ANDESITE_SMOOTH("minecraft:stone", "andesite_smooth", 1, 6, "blocks/stone_andesite_smooth.png", 0xff828382, false), + B_2_0_GRASS("minecraft:grass", null, 2, 0, "blocks/grass_side_carried.png", 0xff939393, true), + B_3_0_DIRT("minecraft:dirt", null, 3, 0, "blocks/dirt.png", 0xff866043, true), + B_4_0_COBBLESTONE("minecraft:cobblestone", null, 4, 0, "blocks/cobblestone.png", 0xff7a7a7a, false), + B_5_0_PLANKS_OAK("minecraft:planks", "oak", 5, 0, "blocks/planks_oak.png", 0xff9c7f4e, false), + B_5_1_PLANKS_SPRUCE("minecraft:planks", "spruce", 5, 1, "blocks/planks_spruce.png", 0xff5a3d0d, false), + B_5_2_PLANKS_BIRCH("minecraft:planks", "birch", 5, 2, "blocks/planks_birch.png", 0xffdabd8d, false), + B_5_3_PLANKS_JUNGLE("minecraft:planks", "jungle", 5, 3, "blocks/planks_jungle.png", 0xffBa7d5d, false), + B_5_4_PLANKS_ACACIA("minecraft:planks", "acacia", 5, 4, "blocks/planks_acacia.png", 0xff934f39, false), + B_5_5_PLANKS_BIG_OAK("minecraft:planks", "big_oak", 5, 5, "blocks/planks_big_oak.png", 0xff3b260f, false), + B_6_0_SAPLING_OAK("minecraft:sapling", "oak", 6, 0, "blocks/sapling_oak.png", 0x6b476625, false), + B_6_1_SAPLING_SPRUCE("minecraft:sapling", "spruce", 6, 1, "blocks/sapling_spruce.png", 0x53333a21, false), + B_6_2_SAPLING_BIRCH("minecraft:sapling", "birch", 6, 2, "blocks/sapling_birch.png", 0x6b769654, false), + B_6_3_SAPLING_JUNGLE("minecraft:sapling", "jungle", 6, 3, "blocks/sapling_jungle.png", 0x55305612, false), + B_6_4_SAPLING_ACACIA("minecraft:sapling", "acacia", 6, 4, "blocks/sapling_acacia.png", 0xff718919, false), + B_6_5_SAPLING_BIG_OAK("minecraft:sapling", "big_oak", 6, 5, "blocks/sapling_roofed_oak.png", 0xff6f522d, false), + B_7_0_BEDROCK("minecraft:bedrock", null, 7, 0, "blocks/bedrock.png", 0xff535353, false), + B_8_0_FLOWING_WATER("minecraft:flowing_water", null, 8, 0, "blocks/water_flow.png", 0x802e43f4, false), + B_9_0_WATER("minecraft:water", null, 9, 0, "blocks/water_still.png", 0x802e43f4, false), + B_10_0_FLOWING_LAVA("minecraft:flowing_lava", null, 10, 0, "blocks/lava_flow.png", 0xf0d45a12, false), + B_11_0_LAVA("minecraft:lava", null, 11, 0, "blocks/lava_still.png", 0xf0d45a12, false), + B_12_0_SAND_DEFAULT("minecraft:sand", "default", 12, 0, "blocks/sand.png", 0xffdbd3a0, false), + B_12_1_SAND_RED("minecraft:sand", "red", 12, 1, "blocks/red_sand.png", 0xffa7531f, false), + B_13_0_GRAVEL("minecraft:gravel", null, 13, 0, "blocks/gravel.png", 0xff7e7c7a, false), + B_14_0_GOLD_ORE("minecraft:gold_ore", null, 14, 0, "blocks/gold_ore.png", 0xff8f8b7c, false), + B_15_0_IRON_ORE("minecraft:iron_ore", null, 15, 0, "blocks/iron_ore.png", 0xff87827e, false), + B_16_0_COAL_ORE("minecraft:coal_ore", null, 16, 0, "blocks/coal_ore.png", 0xff737373, false), + B_17_0_LOG_OAK("minecraft:log", "oak", 17, 0, "blocks/log_oak.png", 0xff9a7d4d, false), + B_17_1_LOG_SPRUCE("minecraft:log", "spruce", 17, 1, "blocks/log_spruce.png", 0xff5a3d0d, false), + B_17_2_LOG_BIRCH("minecraft:log", "birch", 17, 2, "blocks/log_birch.png", 0xffdabd8d, false), + B_17_3_LOG_JUNGLE("minecraft:log", "jungle", 17, 3, "blocks/log_jungle.png", 0xffBa7d5d, false), + B_18_0_LEAVES_OAK("minecraft:leaves", "oak", 18, 0, "blocks/leaves_oak.png", 0xff878787, true), + B_18_1_LEAVES_SPRUCE("minecraft:leaves", "spruce", 18, 1, "blocks/leaves_spruce.png", 0xff132613, true), + B_18_2_LEAVES_BIRCH("minecraft:leaves", "birch", 18, 2, "blocks/leaves_birch.png", 0xff283816, true), + B_18_3_LEAVES_JUNGLE("minecraft:leaves", "jungle", 18, 3, "blocks/leaves_jungle.png", 0xff918e86, true), + B_19_0_SPONGE_DRY("minecraft:sponge", "dry", 19, 0, "blocks/sponge_dry.png", 0xffb6b639, false), + B_19_1_SPONGE_WET("minecraft:sponge", "wet", 19, 1, "blocks/sponge_wet.png", 0xff9b9a33, false), + B_20_0_GLASS("minecraft:glass", null, 20, 0, "blocks/glass.png", 0x46daf0f4, false), + B_21_0_LAPIS_ORE("minecraft:lapis_ore", null, 21, 0, "blocks/lapis_ore.png", 0xff667086, false), + B_22_0_LAPIS_BLOCK("minecraft:lapis_block", null, 22, 0, "blocks/lapis_block.png", 0xff1d47a5, false), + B_23_0_DISPENSER("minecraft:dispenser", null, 23, 0, "blocks/dispenser.png", 0xff606060, false), + B_24_0_SANDSTONE_DEFAULT("minecraft:sandstone", "default", 24, 0, "blocks/sandstone_default.png", 0xffdad29e, false), + B_24_1_SANDSTONE_CHISELED("minecraft:sandstone", "chiseled", 24, 1, "blocks/sandstone_chiseled.png", 0xffdad1a2, false), + B_24_2_SANDSTONE_SMOOTH("minecraft:sandstone", "smooth", 24, 2, "blocks/sandstone_smooth.png", 0xffdad1a2, false), + B_25_0_NOTEBLOCK("minecraft:noteblock", null, 25, 0, "blocks/noteblock.png", 0xff644332, false), + B_26_0_BED("minecraft:bed", null, 26, 0, "blocks/bed.png", 0xff8e1616, false), + B_27_0_GOLDEN_RAIL("minecraft:golden_rail", null, 27, 0, "blocks/golden_rail.png", 0xab9a6846, false), + B_28_0_DETECTOR_RAIL("minecraft:detector_rail", null, 28, 0, "blocks/detector_rail.png", 0x9b786559, false), + B_29_0_STICKY_PISTON("minecraft:sticky_piston", null, 29, 0, "blocks/sticky_piston.png", 0xff8d9263, false), + B_30_0_WEB("minecraft:web", null, 30, 0, "blocks/web.png", 0x68dcdcdc, false), + B_31_1_TALLGRASS_FERN("minecraft:tallgrass", "fern", 31, 1, "blocks/tallgrass_fern.png", 0xff747474, true), + B_31_2_TALLGRASS_GRASS("minecraft:tallgrass", "grass", 31, 2, "blocks/tallgrass_grass.png", 0x4e787878, true), + B_32_0_DEADBUSH("minecraft:deadbush", null, 32, 0, "blocks/deadbush.png", 0x517b4f19, false), + B_33_0_PISTON("minecraft:piston", null, 33, 0, "blocks/piston.png", 0xff998159, false), + B_34_0_PISTONARMCOLLISION("minecraft:pistonArmCollision", null, 34, 0, "blocks/pistonArmCollision.png", 0xff9c7f4e, false), + B_35_0_WOOL_WHITE("minecraft:wool", "white", 35, 0, "blocks/wool_colored_white.png", 0xffdddddd, false), + B_35_1_WOOL_ORANGE("minecraft:wool", "orange", 35, 1, "blocks/wool_colored_orange.png", 0xffdb7d3e, false), + B_35_2_WOOL_MAGENTA("minecraft:wool", "magenta", 35, 2, "blocks/wool_colored_magenta.png", 0xffb350bc, false), + B_35_3_WOOL_LIGHT_BLUE("minecraft:wool", "light_blue", 35, 3, "blocks/wool_colored_light_blue.png", 0xff6a8ac9, false), + B_35_4_WOOL_YELLOW("minecraft:wool", "yellow", 35, 4, "blocks/wool_colored_yellow.png", 0xffb1a627, false), + B_35_5_WOOL_LIME("minecraft:wool", "lime", 35, 5, "blocks/wool_colored_lime.png", 0xff41ae38, false), + B_35_6_WOOL_PINK("minecraft:wool", "pink", 35, 6, "blocks/wool_colored_pink.png", 0xffd08499, false), + B_35_7_WOOL_GRAY("minecraft:wool", "gray", 35, 7, "blocks/wool_colored_gray.png", 0xff404040, false), + B_35_8_WOOL_SILVER("minecraft:wool", "silver", 35, 8, "blocks/wool_colored_silver.png", 0xff9aa1a1, false), + B_35_9_WOOL_CYAN("minecraft:wool", "cyan", 35, 9, "blocks/wool_colored_cyan.png", 0xff2e6e89, false), + B_35_10_WOOL_PURPLE("minecraft:wool", "purple", 35, 10, "blocks/wool_colored_purple.png", 0xff7e3db5, false), + B_35_11_WOOL_BLUE("minecraft:wool", "blue", 35, 11, "blocks/wool_colored_blue.png", 0xff2e388d, false), + B_35_12_WOOL_BROWN("minecraft:wool", "brown", 35, 12, "blocks/wool_colored_brown.png", 0xff4f321f, false), + B_35_13_WOOL_GREEN("minecraft:wool", "green", 35, 13, "blocks/wool_colored_green.png", 0xff35461b, false), + B_35_14_WOOL_RED("minecraft:wool", "red", 35, 14, "blocks/wool_colored_red.png", 0xff963430, false), + B_35_15_WOOL_BLACK("minecraft:wool", "black", 35, 15, "blocks/wool_colored_black.png", 0xff191616, false), + B_36_0_ELEMENT0("minecraft:element_0", "unknown", 36, 0, "blocks/coal_ore.png", 0xff191616, false), + B_36_1_ELEMENT0("minecraft:element_0", "unknown", 36, 1, "blocks/coal_ore.png", 0xff191616, false), + B_36_2_ELEMENT0("minecraft:element_0", "unknown", 36, 2, "blocks/coal_ore.png", 0xff191616, false), + B_36_3_ELEMENT0("minecraft:element_0", "unknown", 36, 3, "blocks/coal_ore.png", 0xff191616, false), + B_36_4_ELEMENT0("minecraft:element_0", "unknown", 36, 4, "blocks/coal_ore.png", 0xff191616, false), + B_36_5_ELEMENT0("minecraft:element_0", "unknown", 36, 5, "blocks/coal_ore.png", 0xff191616, false), + B_36_6_ELEMENT0("minecraft:element_0", "unknown", 36, 6, "blocks/coal_ore.png", 0xff191616, false), + B_36_7_ELEMENT0("minecraft:element_0", "unknown", 36, 7, "blocks/coal_ore.png", 0xff191616, false), + B_36_8_ELEMENT0("minecraft:element_0", "unknown", 36, 8, "blocks/coal_ore.png", 0xff191616, false), + B_36_9_ELEMENT0("minecraft:element_0", "unknown", 36, 9, "blocks/coal_ore.png", 0xff191616, false), + B_36_10_ELEMENT0("minecraft:element_0", "unknown", 36, 10, "blocks/coal_ore.png", 0xff191616, false), + B_36_11_ELEMENT0("minecraft:element_0", "unknown", 36, 11, "blocks/coal_ore.png", 0xff191616, false), + B_36_12_ELEMENT0("minecraft:element_0", "unknown", 36, 12, "blocks/coal_ore.png", 0xff191616, false), + B_36_13_ELEMENT0("minecraft:element_0", "unknown", 36, 13, "blocks/coal_ore.png", 0xff191616, false), + B_36_14_ELEMENT0("minecraft:element_0", "unknown", 36, 14, "blocks/coal_ore.png", 0xff191616, false), + B_36_15_ELEMENT0("minecraft:element_0", "unknown", 36, 15, "blocks/coal_ore.png", 0xff191616, false), + B_37_0_YELLOW_FLOWER("minecraft:yellow_flower", null, 37, 0, "blocks/yellow_flower.png", 0x1e6ca200, false), + B_38_0_RED_FLOWER_POPPY("minecraft:red_flower", "poppy", 38, 0, "blocks/flower_poppy.png", 0x1d8a2b0d, false), + B_38_1_RED_FLOWER_BLUE_ORCHID("minecraft:red_flower", "blue_orchid", 38, 1, "blocks/flower_blue_orchid.png", 0x1d188fd3, false), + B_38_2_RED_FLOWER_ALLIUM("minecraft:red_flower", "allium", 38, 2, "blocks/flower_allium.png", 0x1ddbb7f8, false), + B_38_3_RED_FLOWER_HOUSTONIA("minecraft:red_flower", "houstonia", 38, 3, "blocks/flower_houstonia.png", 0x1defef99, false), + B_38_4_RED_FLOWER_TULIP_RED("minecraft:red_flower", "tulip_red", 38, 4, "blocks/flower_tulip_red.png", 0x1dbd2604, false), + B_38_5_RED_FLOWER_TULIP_ORANGE("minecraft:red_flower", "tulip_orange", 38, 5, "blocks/flower_tulip_orange.png", 0x1dd06713, false), + B_38_6_RED_FLOWER_TULIP_WHITE("minecraft:red_flower", "tulip_white", 38, 6, "blocks/flower_tulip_white.png", 0x1df9f9f9, false), + B_38_7_RED_FLOWER_TULIP_PINK("minecraft:red_flower", "tulip_pink", 38, 7, "blocks/flower_tulip_pink.png", 0x1dbeb3be, false), + B_38_8_RED_FLOWER_OXEYE_DAISY("minecraft:red_flower", "oxeye_daisy", 38, 8, "blocks/flower_oxeye_daisy.png", 0x1ddadada, false), + B_39_0_BROWN_MUSHROOM("minecraft:brown_mushroom", null, 39, 0, "blocks/brown_mushroom.png", 0x198a6953, false), + B_40_0_RED_MUSHROOM("minecraft:red_mushroom", null, 40, 0, "blocks/red_mushroom.png", 0x21c33538, false), + B_41_0_GOLD_BLOCK("minecraft:gold_block", null, 41, 0, "blocks/gold_block.png", 0xfff9ec4e, false), + B_42_0_IRON_BLOCK("minecraft:iron_block", null, 42, 0, "blocks/iron_block.png", 0xffdbdbdb, false), + B_43_0_DOUBLE_STONE_SLAB_STONE("minecraft:double_stone_slab", "stone", 43, 0, "blocks/double_stone_slab_stone.png", 0xff9f9f9f, false), + B_43_1_DOUBLE_STONE_SLAB_SAND("minecraft:double_stone_slab", "sand", 43, 1, "blocks/double_stone_slab_sand.png", 0xffdad29e, false), + B_43_2_DOUBLE_STONE_SLAB_WOOD("minecraft:double_stone_slab", "wood", 43, 2, "blocks/double_stone_slab_wood.png", 0xff9c7f4e, false), + B_43_3_DOUBLE_STONE_SLAB_COBBLE("minecraft:double_stone_slab", "cobble", 43, 3, "blocks/double_stone_slab_cobble.png", 0xff7a7a7a, false), + B_43_4_DOUBLE_STONE_SLAB_BRICK("minecraft:double_stone_slab", "brick", 43, 4, "blocks/double_stone_slab_brick.png", 0xff926356, false), + B_43_5_DOUBLE_STONE_SLAB_SMOOTH_STONE_BRICK("minecraft:double_stone_slab", "smooth_stone_brick", 43, 5, "blocks/double_stone_slab_smooth_stone_brick.png", 0xff7d7d7d, false), + B_43_6_DOUBLE_STONE_SLAB_QUARTZ("minecraft:double_stone_slab", "quartz", 43, 6, "blocks/double_stone_slab_quartz.png", 0xff2c161a, false), + B_43_7_DOUBLE_STONE_SLAB_NETHER_BRICK("minecraft:double_stone_slab", "nether_brick", 43, 7, "blocks/double_stone_slab_nether_brick.png", 0xffece9e2, false), + B_43_8_DOUBLE_STONE_SLAB_RED_SANDSTONE("minecraft:double_stone_slab", "red_sandstone", 43, 8, "blocks/double_stone_slab_red_sandstone.png", 0xff9f9f9f, false), + B_44_0_STONE_SLAB_STONE("minecraft:stone_slab", "stone", 44, 0, "blocks/stone_slab_side.png", 0xff9f9f9f, false), + B_44_1_STONE_SLAB_SAND("minecraft:stone_slab", "sand", 44, 1, "blocks/stone_slab_side.png", 0xffdad29e, false), + B_44_2_STONE_SLAB_WOOD("minecraft:stone_slab", "wood", 44, 2, "blocks/stone_slab_side.png", 0xff9c7f4e, false), + B_44_3_STONE_SLAB_COBBLE("minecraft:stone_slab", "cobble", 44, 3, "blocks/stone_slab_side.png", 0xff7a7a7a, false), + B_44_4_STONE_SLAB_BRICK("minecraft:stone_slab", "brick", 44, 4, "blocks/stone_slab_side.png", 0xff926356, false), + B_44_5_STONE_SLAB_SMOOTH_STONE_BRICK("minecraft:stone_slab", "smooth_stone_brick", 44, 5, "blocks/stone_slab_side.png", 0xff7d7d7d, false), + B_44_6_STONE_SLAB_QUARTZ("minecraft:stone_slab", "quartz", 44, 6, "blocks/stone_slab_side.png", 0xff2c161a, false), + B_44_7_STONE_SLAB_NETHER_BRICK("minecraft:stone_slab", "nether_brick", 44, 7, "blocks/stone_slab_side.png", 0xffece9e2, false), + B_45_0_BRICK_BLOCK("minecraft:brick_block", null, 45, 0, "blocks/brick_block.png", 0xff926356, false), + B_46_0_TNT("minecraft:tnt", null, 46, 0, "blocks/tnt.png", 0xff82412f, false), + B_47_0_BOOKSHELF("minecraft:bookshelf", null, 47, 0, "blocks/bookshelf.png", 0xff6b5839, false), + B_48_0_MOSSY_COBBLESTONE("minecraft:mossy_cobblestone", null, 48, 0, "blocks/mossy_cobblestone.png", 0xff677967, false), + B_49_0_OBSIDIAN("minecraft:obsidian", null, 49, 0, "blocks/obsidian.png", 0xff14121d, false), + B_50_0_TORCH("minecraft:torch", null, 50, 0, "blocks/torch.png", 0x13826a3a, false), + B_51_0_FIRE("minecraft:fire", null, 51, 0, "blocks/fire.png", 0x8bd38c35, false), + B_52_0_MOB_SPAWNER("minecraft:mob_spawner", null, 52, 0, "blocks/mob_spawner.png", 0x9b1a2731, false), + B_53_0_OAK_STAIRS("minecraft:oak_stairs", null, 53, 0, "blocks/oak_stairs.png", 0xff9c7f4e, false), + B_54_0_CHEST("minecraft:chest", null, 54, 0, "blocks/chest_front.png", 0xc86f5739, false), + B_55_0_REDSTONE_WIRE("minecraft:redstone_wire", null, 55, 0, "blocks/redstone_wire.png", 0x80fa1010, false), + B_56_0_DIAMOND_ORE("minecraft:diamond_ore", null, 56, 0, "blocks/diamond_ore.png", 0xff818c8f, false), + B_57_0_DIAMOND_BLOCK("minecraft:diamond_block", null, 57, 0, "blocks/diamond_block.png", 0xff61dbd5, false), + B_58_0_CRAFTING_TABLE("minecraft:crafting_table", null, 58, 0, "blocks/crafting_table.png", 0xff6b472a, false), + B_59_0_WHEAT("minecraft:wheat", null, 59, 0, "blocks/wheat.png", 0x0500b312, false), + B_60_0_FARMLAND("minecraft:farmland", null, 60, 0, "blocks/farmland.png", 0xff734b2d, false), + B_61_0_FURNACE("minecraft:furnace", null, 61, 0, "blocks/furnace.png", 0xff606060, false), + B_62_0_LIT_FURNACE("minecraft:lit_furnace", null, 62, 0, "blocks/lit_furnace.png", 0xff606060, false), + B_63_0_STANDING_SIGN("minecraft:standing_sign", null, 63, 0, "blocks/standing_sign.png", 0x566f5739, false), + B_64_0_WOODEN_DOOR("minecraft:wooden_door", null, 64, 0, "blocks/wooden_door.png", 0xcf866733, false), + B_65_0_LADDER("minecraft:ladder", null, 65, 0, "blocks/ladder.png", 0x8f795f34, false), + B_66_0_RAIL("minecraft:rail", null, 66, 0, "blocks/rail.png", 0x8f796c58, false), + B_67_0_STONE_STAIRS("minecraft:stone_stairs", null, 67, 0, "blocks/stone_stairs.png", 0xff7a7a7a, false), + B_68_0_WALL_SIGN("minecraft:wall_sign", null, 68, 0, "blocks/wall_sign.png", 0x206f5739, false), + B_69_0_LEVER("minecraft:lever", null, 69, 0, "blocks/lever.png", 0x136a5940, false), + B_70_0_STONE_PRESSURE_PLATE("minecraft:stone_pressure_plate", null, 70, 0, "blocks/stone_pressure_plate.png", 0xff7d7d7d, false), + B_71_0_IRON_DOOR("minecraft:iron_door", null, 71, 0, "blocks/iron_door.png", 0xcfbababa, false), + B_72_0_WOODEN_PRESSURE_PLATE("minecraft:wooden_pressure_plate", null, 72, 0, "blocks/wooden_pressure_plate.png", 0xff9c7f4e, false), + B_73_0_REDSTONE_ORE("minecraft:redstone_ore", null, 73, 0, "blocks/redstone_ore.png", 0xff846b6b, false), + B_74_0_LIT_REDSTONE_ORE("minecraft:lit_redstone_ore", null, 74, 0, "blocks/lit_redstone_ore.png", 0xff846b6b, false), + B_75_0_UNLIT_REDSTONE_TORCH("minecraft:unlit_redstone_torch", null, 75, 0, "blocks/unlit_redstone_torch.png", 0x465d3e26, false), + B_76_0_REDSTONE_TORCH("minecraft:redstone_torch", null, 76, 0, "blocks/redstone_torch.png", 0x46a74b29, false), + B_77_0_STONE_BUTTON("minecraft:stone_button", null, 77, 0, "blocks/stone_button.png", 0x28565656, false), + B_78_0_SNOW_LAYER("minecraft:snow_layer", null, 78, 0, "blocks/snow_layer.png", 0xffeffbfb, false), + B_79_0_ICE("minecraft:ice", null, 79, 0, "blocks/ice.png", 0x9f7dadff, false), + B_80_0_SNOW("minecraft:snow", null, 80, 0, "blocks/snow.png", 0xffeffbfb, false), + B_81_0_CACTUS("minecraft:cactus", null, 81, 0, "blocks/cactus.png", 0xc30d6318, false), + B_82_0_CLAY("minecraft:clay", null, 82, 0, "blocks/clay.png", 0xff9ea4b0, false), + B_83_0_REEDS("minecraft:reeds", null, 83, 0, "blocks/reeds.png", 0x8c94c065, false), + + B_84_0_JUKEBOX("minecraft:jukebox", null, 84, 0, "blocks/fence_birch_fence.png", 0x8f463822, false), + + B_85_0_FENCE_FENCE("minecraft:fence", "fence", 85, 0, "blocks/fence_fence.png", 0x8f463822, false), + B_85_1_FENCE_SPRUCE_FENCE("minecraft:fence", "spruce_fence", 85, 1, "blocks/fence_spruce_fence.png", 0x8f5a3d0d, false), + B_85_2_FENCE_BIRCH_FENCE("minecraft:fence", "birch_fence", 85, 2, "blocks/fence_birch_fence.png", 0x8fdabd8d, false), + B_85_3_FENCE_JUNGLE_FENCE("minecraft:fence", "jungle_fence", 85, 3, "blocks/fence_jungle_fence.png", 0x8fBa7d5d, false), + B_85_4_FENCE_ACACIA_FENCE("minecraft:fence", "acacia_fence", 85, 4, "blocks/fence_acacia_fence.png", 0x8f934f39, false), + B_85_5_FENCE_DARK_OAK_FENCE("minecraft:fence", "dark_oak_fence", 85, 5, "blocks/fence_dark_oak_fence.png", 0x8f2d2213, false), + B_86_0_PUMPKIN("minecraft:pumpkin", null, 86, 0, "blocks/pumpkin.png", 0xffc07615, false), + B_87_0_NETHERRACK("minecraft:netherrack", null, 87, 0, "blocks/netherrack.png", 0xff6f3634, false), + B_88_0_SOUL_SAND("minecraft:soul_sand", null, 88, 0, "blocks/soul_sand.png", 0xff544033, false), + B_89_0_GLOWSTONE("minecraft:glowstone", null, 89, 0, "blocks/glowstone.png", 0xff8f7645, false), + B_90_0_PORTAL("minecraft:portal", null, 90, 0, "blocks/portal.png", 0xc8410491, false), + B_91_0_LIT_PUMPKIN("minecraft:lit_pumpkin", null, 91, 0, "blocks/lit_pumpkin.png", 0xffc07615, false), + B_92_0_CAKE("minecraft:cake", null, 92, 0, "blocks/cake.png", 0xc3e4cdce, false), + B_93_0_UNPOWERED_REPEATER("minecraft:unpowered_repeater", null, 93, 0, "blocks/unpowered_repeater.png", 0xff979393, false), + B_94_0_POWERED_REPEATER("minecraft:powered_repeater", null, 94, 0, "blocks/powered_repeater.png", 0xffa09393, false), + B_95_0_INVISIBLEBEDROCK("minecraft:invisibleBedrock", null, 95, 0, "blocks/invisibleBedrock.png", 0x3c282828, false), + B_96_0_TRAPDOOR("minecraft:trapdoor", null, 96, 0, "blocks/trapdoor.png", 0xdb7e5d2d, false), + B_97_0_MONSTER_EGG_STONE("minecraft:monster_egg", "stone", 97, 0, "blocks/monster_egg_stone.png", 0xff7d7d7d, false), + B_97_1_MONSTER_EGG_COBBLE("minecraft:monster_egg", "cobble", 97, 1, "blocks/monster_egg_cobble.png", 0xff7a7a7a, false), + B_97_2_MONSTER_EGG_BRICK("minecraft:monster_egg", "brick", 97, 2, "blocks/monster_egg_brick.png", 0xff7a7a7a, false), + B_97_3_MONSTER_EGG_MOSSYBRICK("minecraft:monster_egg", "mossybrick", 97, 3, "blocks/monster_egg_mossybrick.png", 0xff7b6651, false), + B_97_4_MONSTER_EGG_CRACKEDBRICK("minecraft:monster_egg", "crackedbrick", 97, 4, "blocks/monster_egg_crackedbrick.png", 0xff7b6651, false), + B_97_5_MONSTER_EGG_CHISELEDBRICK("minecraft:monster_egg", "chiseledbrick", 97, 5, "blocks/monster_egg_chiseledbrick.png", 0xff7b6651, false), + B_98_0_STONEBRICK_DEFAULT("minecraft:stonebrick", "default", 98, 0, "blocks/stonebrick_default.png", 0xff7a7a7a, false), + B_98_1_STONEBRICK_MOSSY("minecraft:stonebrick", "mossy", 98, 1, "blocks/stonebrick_mossy.png", 0xff72776a, false), + B_98_2_STONEBRICK_CRACKED("minecraft:stonebrick", "cracked", 98, 2, "blocks/stonebrick_cracked.png", 0xff767676, false), + B_98_3_STONEBRICK_CHISELED("minecraft:stonebrick", "chiseled", 98, 3, "blocks/stonebrick_chiseled.png", 0xff767676, false), + B_98_4_STONEBRICK_SMOOTH("minecraft:stonebrick", "smooth", 98, 4, "blocks/stonebrick_smooth.png", 0xff767676, false), + B_99_0_BROWN_MUSHROOM_BLOCK("minecraft:brown_mushroom_block", null, 99, 0, "blocks/brown_mushroom_block.png", 0xff8d6a53, false), + B_100_0_RED_MUSHROOM_BLOCK("minecraft:red_mushroom_block", null, 100, 0, "blocks/red_mushroom_block.png", 0xffb62524, false), + B_101_0_IRON_BARS("minecraft:iron_bars", null, 101, 0, "blocks/iron_bars.png", 0x736d6c6a, false), + B_102_0_GLASS_PANE("minecraft:glass_pane", null, 102, 0, "blocks/glass_pane.png", 0x1fd3eff4, false), + B_103_0_MELON_BLOCK("minecraft:melon_block", null, 103, 0, "blocks/melon_block.png", 0xff979924, false), + B_104_0_PUMPKIN_STEM("minecraft:pumpkin_stem", null, 104, 0, "blocks/pumpkin_stem.png", 0x1e87b759, false), + B_105_0_MELON_STEM("minecraft:melon_stem", null, 105, 0, "blocks/melon_stem.png", 0x1e87b759, false), + B_106_0_VINE("minecraft:vine", null, 106, 0, "blocks/vine.png", 0x8a6f6f6f, false), + B_107_0_FENCE_GATE("minecraft:fence_gate", null, 107, 0, "blocks/fence_gate.png", 0x7b463822, false), + B_108_0_BRICK_STAIRS("minecraft:brick_stairs", null, 108, 0, "blocks/brick_stairs.png", 0xff926356, false), + B_109_0_STONE_BRICK_STAIRS("minecraft:stone_brick_stairs", null, 109, 0, "blocks/stone_brick_stairs.png", 0xff7a7a7a, false), + B_110_0_MYCELIUM("minecraft:mycelium", null, 110, 0, "blocks/mycelium.png", 0xff6f6369, false), + B_111_0_WATERLILY("minecraft:waterlily", null, 111, 0, "blocks/waterlily.png", 0x93335a21, false), + B_112_0_NETHER_BRICK("minecraft:nether_brick", null, 112, 0, "blocks/nether_brick.png", 0xff2c161a, false), + B_113_0_NETHER_BRICK_FENCE("minecraft:nether_brick_fence", null, 113, 0, "blocks/nether_brick_fence.png", 0xff2c161a, false), + B_114_0_NETHER_BRICK_STAIRS("minecraft:nether_brick_stairs", null, 114, 0, "blocks/nether_brick_stairs.png", 0xff2c161a, false), + B_115_0_NETHER_WART("minecraft:nether_wart", null, 115, 0, "blocks/nether_wart.png", 0x2a6a0e1e, false), + B_116_0_ENCHANTING_TABLE("minecraft:enchanting_table", null, 116, 0, "blocks/enchanting_table.png", 0xff67403b, false), + B_117_0_BREWING_STAND("minecraft:brewing_stand", null, 117, 0, "blocks/brewing_stand.png", 0x767c6751, false), + B_118_0_CAULDRON("minecraft:cauldron", null, 118, 0, "blocks/cauldron.png", 0xff373737, false), + B_119_0_END_PORTAL("minecraft:end_portal", null, 119, 0, "blocks/endframe_top.png", 0xff101010, false), + B_120_0_END_PORTAL_FRAME("minecraft:end_portal_frame", null, 120, 0, "blocks/endframe_side.png", 0xff597560, false), + B_121_0_END_STONE("minecraft:end_stone", null, 121, 0, "blocks/end_stone.png", 0xffdddfa5, false), + B_122_0_DRAGON_EGG("minecraft:dragon_egg", null, 122, 0, "blocks/dragon_egg.png", 0xff0c090f, false), + B_123_0_REDSTONE_LAMP("minecraft:redstone_lamp", null, 123, 0, "blocks/redstone_lamp.png", 0xff462b1a, false), + B_124_0_LIT_REDSTONE_LAMP("minecraft:lit_redstone_lamp", null, 124, 0, "blocks/lit_redstone_lamp.png", 0xff775937, false), + B_125_0_DROPPER("minecraft:dropper", null, 125, 0, "blocks/dropper.png", 0xff9c7f4e, false), + B_126_0_ACTIVATOR_RAIL("minecraft:activator_rail", null, 126, 0, "blocks/activator_rail.png", 0xff9c7f4e, false), + B_127_0_COCOA("minecraft:cocoa", null, 127, 0, "blocks/cocoa.png", 0x2e8a8c40, false), + B_128_0_SANDSTONE_STAIRS("minecraft:sandstone_stairs", null, 128, 0, "blocks/sandstone_stairs.png", 0xffdad29e, false), + B_129_0_EMERALD_ORE("minecraft:emerald_ore", null, 129, 0, "blocks/emerald_ore.png", 0xff6d8074, false), + B_130_0_ENDER_CHEST("minecraft:ender_chest", null, 130, 0, "blocks/ender_chest_front.png", 0xc82c3e40, false), + B_131_0_TRIPWIRE_HOOK("minecraft:tripwire_hook", null, 131, 0, "blocks/tripwire_hook.png", 0x2d8a8171, false), + B_132_0_TRIPWIRE("minecraft:tripWire", null, 132, 0, "blocks/tripWire.png", 0x2d818181, false), + B_133_0_EMERALD_BLOCK("minecraft:emerald_block", null, 133, 0, "blocks/emerald_block.png", 0xff51d975, false), + B_134_0_SPRUCE_STAIRS("minecraft:spruce_stairs", null, 134, 0, "blocks/spruce_stairs.png", 0xff5a3d0d, false), + B_135_0_BIRCH_STAIRS("minecraft:birch_stairs", null, 135, 0, "blocks/birch_stairs.png", 0xffdabd8d, false), + B_136_0_JUNGLE_STAIRS("minecraft:jungle_stairs", null, 136, 0, "blocks/jungle_stairs.png", 0xffBa7d5d, false), + B_138_0_BEACON("minecraft:beacon", null, 138, 0, "blocks/beacon.png", 0xff74ddd7, false), + B_139_0_COBBLESTONE_WALL_NORMAL("minecraft:cobblestone_wall", "normal", 139, 0, "blocks/cobblestone_wall_normal.png", 0xff7a7a7a, false), + B_139_1_COBBLESTONE_WALL_MOSSY("minecraft:cobblestone_wall", "mossy", 139, 1, "blocks/cobblestone_wall_mossy.png", 0xff506a50, false), + B_140_0_FLOWER_POT("minecraft:flower_pot", null, 140, 0, "blocks/flower_pot.png", 0x31764133, false), + B_141_0_CARROTS("minecraft:carrots", null, 141, 0, "blocks/carrots.png", 0x0901ab10, false), + B_142_0_POTATOES("minecraft:potatoes", null, 142, 0, "blocks/potatoes.png", 0x0901ab10, false), + B_143_0_WOODEN_BUTTON("minecraft:wooden_button", null, 143, 0, "blocks/wooden_button.png", 0x2878613e, false), + B_144_0_SKULL("minecraft:skull", null, 144, 0, "blocks/skull.png", 0x8c8c8c8c, false), + B_145_0_ANVIL_INTACT("minecraft:anvil", "intact", 145, 0, "blocks/anvil_intact.png", 0x9f403c3c, false), + B_145_4_ANVIL_SLIGHTLY_DAMAGED("minecraft:anvil", "slightly_damaged", 145, 4, "blocks/anvil_slightly_damaged.png", 0x9f403c3c, false), + B_145_8_ANVIL_VERY_DAMAGED("minecraft:anvil", "very_damaged", 145, 8, "blocks/anvil_very_damaged.png", 0x9f403c3c, false), + B_146_0_TRAPPED_CHEST("minecraft:trapped_chest", null, 146, 0, "blocks/chest_front.png", 0xfe6f5739, false), + B_147_0_LIGHT_WEIGHTED_PRESSURE_PLATE("minecraft:light_weighted_pressure_plate", null, 147, 0, "blocks/light_weighted_pressure_plate.png", 0xc8f9ec4e, false), + B_148_0_HEAVY_WEIGHTED_PRESSURE_PLATE("minecraft:heavy_weighted_pressure_plate", null, 148, 0, "blocks/heavy_weighted_pressure_plate.png", 0xc8dbdbdb, false), + B_149_0_UNPOWERED_COMPARATOR("minecraft:unpowered_comparator", null, 149, 0, "blocks/unpowered_comparator.png", 0xff9c9695, false), + B_150_0_POWERED_COMPARATOR("minecraft:powered_comparator", null, 150, 0, "blocks/powered_comparator.png", 0xffa59594, false), + B_151_0_DAYLIGHT_DETECTOR("minecraft:daylight_detector", null, 151, 0, "blocks/daylight_detector.png", 0xff82745e, false), + B_152_0_REDSTONE_BLOCK("minecraft:redstone_block", null, 152, 0, "blocks/redstone_block.png", 0xffab1b09, false), + B_153_0_QUARTZ_ORE("minecraft:quartz_ore", null, 153, 0, "blocks/quartz_ore.png", 0xffd9d1c8, false), + B_154_0_HOPPER("minecraft:hopper", null, 154, 0, "blocks/hopper.png", 0xff3e3e3e, false), + B_155_0_QUARTZ_BLOCK_DEFAULT("minecraft:quartz_block", "default", 155, 0, "blocks/quartz_block_default.png", 0xffece9e2, false), + B_155_1_QUARTZ_BLOCK_CHISELED("minecraft:quartz_block", "chiseled", 155, 1, "blocks/quartz_block_chiseled.png", 0xffe7e4db, false), + B_155_2_QUARTZ_BLOCK_LINES("minecraft:quartz_block", "lines", 155, 2, "blocks/quartz_block_lines.png", 0xffe8e5dd, false), + B_155_3_QUARTZ_BLOCK_DEFAULT("minecraft:quartz_block", "default", 155, 3, "blocks/quartz_block_default.png", 0xffe7e3db, false), + B_156_0_QUARTZ_STAIRS("minecraft:quartz_stairs", null, 156, 0, "blocks/quartz_stairs.png", 0xffece9e2, false), + B_157_0_DOUBLE_WOODEN_SLAB_OAK("minecraft:double_wooden_slab", "oak", 157, 0, "blocks/planks_oak.png", 0xb4907449, false), + B_157_1_DOUBLE_WOODEN_SLAB_SPRUCE("minecraft:double_wooden_slab", "spruce", 157, 1, "blocks/planks_spruce.png", 0xff5a3d0d, false), + B_157_2_DOUBLE_WOODEN_SLAB_BIRCH("minecraft:double_wooden_slab", "birch", 157, 2, "blocks/planks_birch.png", 0xb4dabd8d, false), + B_157_3_DOUBLE_WOODEN_SLAB_JUNGLE("minecraft:double_wooden_slab", "jungle", 157, 3, "blocks/planks_jungle.png", 0xb4Ba7d5d, false), + B_157_4_DOUBLE_WOODEN_SLAB_ACACIA("minecraft:double_wooden_slab", "acacia", 157, 4, "blocks/planks_acacia.png", 0xb4934f39, false), + B_157_5_DOUBLE_WOODEN_SLAB_BIG_OAK("minecraft:double_wooden_slab", "big_oak", 157, 5, "blocks/planks_big_oak.png", 0xb4907449, false), + B_158_0_WOODEN_SLAB_OAK("minecraft:wooden_slab", "oak", 158, 0, "blocks/wooden_slab_oak.png", 0xff907449, false), + B_158_1_WOODEN_SLAB_SPRUCE("minecraft:wooden_slab", "spruce", 158, 1, "blocks/wooden_slab_spruce.png", 0xff5a3d0d, false), + B_158_2_WOODEN_SLAB_BIRCH("minecraft:wooden_slab", "birch", 158, 2, "blocks/wooden_slab_birch.png", 0xffdabd8d, false), + B_158_3_WOODEN_SLAB_JUNGLE("minecraft:wooden_slab", "jungle", 158, 3, "blocks/wooden_slab_jungle.png", 0xffBa7d5d, false), + B_158_4_WOODEN_SLAB_ACACIA("minecraft:wooden_slab", "acacia", 158, 4, "blocks/wooden_slab_acacia.png", 0xff934f39, false), + B_158_5_WOODEN_SLAB_BIG_OAK("minecraft:wooden_slab", "big_oak", 158, 5, "blocks/wooden_slab_big_oak.png", 0xff907449, false), + B_159_0_STAINED_HARDENED_CLAY_WHITE("minecraft:stained_hardened_clay", "white", 159, 0, "blocks/hardened_clay_stained_white.png", 0xff836f64, false), + B_159_1_STAINED_HARDENED_CLAY_ORANGE("minecraft:stained_hardened_clay", "orange", 159, 1, "blocks/hardened_clay_stained_orange.png", 0xff9d5021, false), + B_159_2_STAINED_HARDENED_CLAY_MAGENTA("minecraft:stained_hardened_clay", "magenta", 159, 2, "blocks/hardened_clay_stained_magenta.png", 0xff915369, false), + B_159_3_STAINED_HARDENED_CLAY_LIGHT_BLUE("minecraft:stained_hardened_clay", "light_blue", 159, 3, "blocks/hardened_clay_stained_light_blue.png", 0xff706b87, false), + B_159_4_STAINED_HARDENED_CLAY_YELLOW("minecraft:stained_hardened_clay", "yellow", 159, 4, "blocks/hardened_clay_stained_yellow.png", 0xffb5801f, false), + B_159_5_STAINED_HARDENED_CLAY_LIME("minecraft:stained_hardened_clay", "lime", 159, 5, "blocks/hardened_clay_stained_lime.png", 0xff617030, false), + B_159_6_STAINED_HARDENED_CLAY_PINK("minecraft:stained_hardened_clay", "pink", 159, 6, "blocks/hardened_clay_stained_pink.png", 0xff9c4848, false), + B_159_7_STAINED_HARDENED_CLAY_GRAY("minecraft:stained_hardened_clay", "gray", 159, 7, "blocks/hardened_clay_stained_gray.png", 0xff392721, false), + B_159_8_STAINED_HARDENED_CLAY_SILVER("minecraft:stained_hardened_clay", "silver", 159, 8, "blocks/hardened_clay_stained_silver.png", 0xff81655b, false), + B_159_9_STAINED_HARDENED_CLAY_CYAN("minecraft:stained_hardened_clay", "cyan", 159, 9, "blocks/hardened_clay_stained_cyan.png", 0xff565959, false), + B_159_10_STAINED_HARDENED_CLAY_PURPLE("minecraft:stained_hardened_clay", "purple", 159, 10, "blocks/hardened_clay_stained_purple.png", 0xff744555, false), + B_159_11_STAINED_HARDENED_CLAY_BLUE("minecraft:stained_hardened_clay", "blue", 159, 11, "blocks/hardened_clay_stained_blue.png", 0xff463857, false), + B_159_12_STAINED_HARDENED_CLAY_BROWN("minecraft:stained_hardened_clay", "brown", 159, 12, "blocks/hardened_clay_stained_brown.png", 0xff492e1f, false), + B_159_13_STAINED_HARDENED_CLAY_GREEN("minecraft:stained_hardened_clay", "green", 159, 13, "blocks/hardened_clay_stained_green.png", 0xff484f26, false), + B_159_14_STAINED_HARDENED_CLAY_RED("minecraft:stained_hardened_clay", "red", 159, 14, "blocks/hardened_clay_stained_red.png", 0xffff382b, false), + B_159_15_STAINED_HARDENED_CLAY_BLACK("minecraft:stained_hardened_clay", "black", 159, 15, "blocks/hardened_clay_stained_black.png", 0xff21120d, false), + B_160_0_STAINED_GLASS_PANE_WHITE("minecraft:stained_glass_pane", "white", 160, 0, "blocks/glass.png", 0x32141414, false), + B_160_1_STAINED_GLASS_PANE_ORANGE("minecraft:stained_glass_pane", "orange", 160, 1, "blocks/glass.png", 0x209d5021, false), + B_160_2_STAINED_GLASS_PANE_MAGENTA("minecraft:stained_glass_pane", "magenta", 160, 2, "blocks/glass.png", 0x20915369, false), + B_160_3_STAINED_GLASS_PANE_LIGHT_BLUE("minecraft:stained_glass_pane", "light_blue", 160, 3, "blocks/glass.png", 0x20706b87, false), + B_160_4_STAINED_GLASS_PANE_YELLOW("minecraft:stained_glass_pane", "yellow", 160, 4, "blocks/glass.png", 0x20b5801f, false), + B_160_5_STAINED_GLASS_PANE_LIME("minecraft:stained_glass_pane", "lime", 160, 5, "blocks/glass.png", 0x20617030, false), + B_160_6_STAINED_GLASS_PANE_PINK("minecraft:stained_glass_pane", "pink", 160, 6, "blocks/glass.png", 0x209c4848, false), + B_160_7_STAINED_GLASS_PANE_GRAY("minecraft:stained_glass_pane", "gray", 160, 7, "blocks/glass.png", 0x20392721, false), + B_160_8_STAINED_GLASS_PANE_SILVER("minecraft:stained_glass_pane", "silver", 160, 8, "blocks/glass.png", 0x2081655b, false), + B_160_9_STAINED_GLASS_PANE_CYAN("minecraft:stained_glass_pane", "cyan", 160, 9, "blocks/glass.png", 0x20565959, false), + B_160_10_STAINED_GLASS_PANE_PURPLE("minecraft:stained_glass_pane", "purple", 160, 10, "blocks/glass.png", 0x20744555, false), + B_160_11_STAINED_GLASS_PANE_BLUE("minecraft:stained_glass_pane", "blue", 160, 11, "blocks/glass.png", 0x20463857, false), + B_160_12_STAINED_GLASS_PANE_BROWN("minecraft:stained_glass_pane", "brown", 160, 12, "blocks/glass.png", 0x20492e1f, false), + B_160_13_STAINED_GLASS_PANE_GREEN("minecraft:stained_glass_pane", "green", 160, 13, "blocks/glass.png", 0x20484f26, false), + B_160_14_STAINED_GLASS_PANE_RED("minecraft:stained_glass_pane", "red", 160, 14, "blocks/glass.png", 0x20ff382b, false), + B_160_15_STAINED_GLASS_PANE_BLACK("minecraft:stained_glass_pane", "black", 160, 15, "blocks/glass.png", 0x2021120d, false), + B_161_0_LEAVES2_ACACIA("minecraft:leaves2", "acacia", 161, 0, "blocks/leaves2_acacia.png", 0xff2e780c, true), + B_161_1_LEAVES2_BIG_OAK("minecraft:leaves2", "big_oak", 161, 1, "blocks/leaves2_big_oak.png", 0xff878787, true), + B_162_0_LOG2_ACACIA("minecraft:log2", "acacia", 162, 0, "blocks/log2_acacia.png", 0xff934f39, false), + B_162_1_LOG2_BIG_OAK("minecraft:log2", "big_oak", 162, 1, "blocks/log2_big_oak.png", 0xff2d2213, false), + B_163_0_ACACIA_STAIRS("minecraft:acacia_stairs", null, 163, 0, "blocks/acacia_stairs.png", 0xff934f39, false), + B_164_0_DARK_OAK_STAIRS("minecraft:dark_oak_stairs", null, 164, 0, "blocks/dark_oak_stairs.png", 0xff2d2213, false), + B_165_0_SLIME("minecraft:slime", null, 165, 0, "blocks/slime.png", 0xc880b672, false), + B_167_0_IRON_TRAPDOOR("minecraft:iron_trapdoor", null, 167, 0, "blocks/iron_trapdoor.png", 0xb4cccccc, false), + B_168_0_PRISMARINE_ROUGH("minecraft:prismarine", "rough", 168, 0, "blocks/prismarine_rough.png", 0xff79Ad7e, false), + B_168_1_PRISMARINE_DARK("minecraft:prismarine", "dark", 168, 1, "blocks/prismarine_dark.png", 0xFF34634e, false), + B_168_2_PRISMARINE_BRICKS("minecraft:prismarine", "bricks", 168, 2, "blocks/prismarine_bricks.png", 0xff59Ad7e, false), + B_169_0_SEALANTERN("minecraft:seaLantern", null, 169, 0, "blocks/seaLantern.png", 0xffe0eae4, false), + B_170_0_HAY_BLOCK("minecraft:hay_block", null, 170, 0, "blocks/hay_block.png", 0xffa3870e, false), + B_171_0_CARPET_WHITE("minecraft:carpet", "white", 171, 0, "blocks/carpet_white.png", 0xffdddddd, false), + B_171_1_CARPET_ORANGE("minecraft:carpet", "orange", 171, 1, "blocks/carpet_orange.png", 0xffdb7d3e, false), + B_171_2_CARPET_MAGENTA("minecraft:carpet", "magenta", 171, 2, "blocks/carpet_magenta.png", 0xffb350bc, false), + B_171_3_CARPET_LIGHT_BLUE("minecraft:carpet", "light_blue", 171, 3, "blocks/carpet_light_blue.png", 0xff6a8ac9, false), + B_171_4_CARPET_YELLOW("minecraft:carpet", "yellow", 171, 4, "blocks/carpet_yellow.png", 0xffb1a627, false), + B_171_5_CARPET_LIME("minecraft:carpet", "lime", 171, 5, "blocks/carpet_lime.png", 0xff41ae38, false), + B_171_6_CARPET_PINK("minecraft:carpet", "pink", 171, 6, "blocks/carpet_pink.png", 0xffd08499, false), + B_171_7_CARPET_GRAY("minecraft:carpet", "gray", 171, 7, "blocks/carpet_gray.png", 0xff404040, false), + B_171_8_CARPET_SILVER("minecraft:carpet", "silver", 171, 8, "blocks/carpet_silver.png", 0xff9aa1a1, false), + B_171_9_CARPET_CYAN("minecraft:carpet", "cyan", 171, 9, "blocks/carpet_cyan.png", 0xff2e6e89, false), + B_171_10_CARPET_PURPLE("minecraft:carpet", "purple", 171, 10, "blocks/carpet_purple.png", 0xff7e3db5, false), + B_171_11_CARPET_BLUE("minecraft:carpet", "blue", 171, 11, "blocks/carpet_blue.png", 0xff2e388d, false), + B_171_12_CARPET_BROWN("minecraft:carpet", "brown", 171, 12, "blocks/carpet_brown.png", 0xff4f321f, false), + B_171_13_CARPET_GREEN("minecraft:carpet", "green", 171, 13, "blocks/carpet_green.png", 0xff35461b, false), + B_171_14_CARPET_RED("minecraft:carpet", "red", 171, 14, "blocks/carpet_red.png", 0xff963430, false), + B_171_15_CARPET_BLACK("minecraft:carpet", "black", 171, 15, "blocks/carpet_black.png", 0xff191616, false), + B_172_0_HARDENED_CLAY("minecraft:hardened_clay", null, 172, 0, "blocks/hardened_clay.png", 0xff5d3828, false), + B_173_0_COAL_BLOCK("minecraft:coal_block", null, 173, 0, "blocks/coal_block.png", 0xff111111, false), + B_174_0_PACKED_ICE("minecraft:packed_ice", null, 174, 0, "blocks/packed_ice.png", 0xff97b3e4, false), + B_175_0_DOUBLE_PLANT_SUNFLOWER("minecraft:double_plant", "sunflower", 175, 0, "blocks/double_plant_sunflower.png", 0xb4d28219, false), + B_175_1_DOUBLE_PLANT_SYRINGA("minecraft:double_plant", "syringa", 175, 1, "blocks/double_plant_syringa.png", 0xb4dec0e2, false), + B_175_2_DOUBLE_PLANT_GRASS("minecraft:double_plant", "grass", 175, 2, "blocks/double_plant_grass.png", 0xb4334e2c, false), + B_175_3_DOUBLE_PLANT_FERN("minecraft:double_plant", "fern", 175, 3, "blocks/double_plant_fern.png", 0xb43d5d34, false), + B_175_4_DOUBLE_PLANT_ROSE("minecraft:double_plant", "rose", 175, 4, "blocks/double_plant_rose.png", 0xb4d10609, false), + B_175_5_DOUBLE_PLANT_PAEONIA("minecraft:double_plant", "paeonia", 175, 5, "blocks/double_plant_paeonia.png", 0xb4d6c1df, false), + + B_176_0_BANNER("minecraft:banner", null, 176, 0, "blocks/double_plant_paeonia.png", 0xff9aa1a1, false), + B_176_8_BANNER("minecraft:banner", null, 176, 8, "blocks/double_plant_paeonia.png", 0xff9aa1a1, false), + B_176_12_BANNER("minecraft:banner", null, 176, 12, "blocks/double_plant_paeonia.png", 0xff9aa1a1, false), + + B_178_0_DAYLIGHT_DETECTOR_INVERTED("minecraft:daylight_detector_inverted", null, 178, 0, "blocks/daylight_detector_inverted.png", 0xffd8c9b5, false), + B_179_0_RED_SANDSTONE_DEFAULT("minecraft:red_sandstone", "default", 179, 0, "blocks/red_sandstone_default.png", 0xffaa561e, false), + B_179_1_RED_SANDSTONE_CHISELED("minecraft:red_sandstone", "chiseled", 179, 1, "blocks/red_sandstone_chiseled.png", 0xffa8551e, false), + B_179_2_RED_SANDSTONE_SMOOTH("minecraft:red_sandstone", "smooth", 179, 2, "blocks/red_sandstone_smooth.png", 0xffcc5e16, false), + B_180_0_RED_SANDSTONE_STAIRS("minecraft:red_sandstone_stairs", null, 180, 0, "blocks/red_sandstone_stairs.png", 0xffaa561e, false), + B_181_0_DOUBLE_STONE_SLAB2_RED_SANDSTONE("minecraft:double_stone_slab2", "red_sandstone", 181, 0, "blocks/double_stone_slab2_red_sandstone.png", 0xffaa561e, false), + B_181_1_DOUBLE_STONE_SLAB2_PURPUR("minecraft:double_stone_slab2", "purpur", 181, 1, "blocks/double_stone_slab2_purpur.png", 0xffa072a0, false), + B_182_0_STONE_SLAB2_RED_SANDSTONE("minecraft:stone_slab2", "red_sandstone", 182, 0, "blocks/stone_slab2_red_sandstone.png", 0xffaa561e, false), + B_182_1_STONE_SLAB2_PURPUR("minecraft:stone_slab2", "purpur", 182, 1, "blocks/stone_slab2_purpur.png", 0xffa072a0, false), + B_183_0_SPRUCE_FENCE_GATE("minecraft:spruce_fence_gate", null, 183, 0, "blocks/spruce_fence_gate.png", 0x8f5a3d0d, false), + B_184_0_BIRCH_FENCE_GATE("minecraft:birch_fence_gate", null, 184, 0, "blocks/birch_fence_gate.png", 0x8fdabd8d, false), + B_185_0_JUNGLE_FENCE_GATE("minecraft:jungle_fence_gate", null, 185, 0, "blocks/jungle_fence_gate.png", 0x8fBa7d5d, false), + B_186_0_DARK_OAK_FENCE_GATE("minecraft:dark_oak_fence_gate", null, 186, 0, "blocks/dark_oak_fence_gate.png", 0x8f2d2213, false), + B_187_0_ACACIA_FENCE_GATE("minecraft:acacia_fence_gate", null, 187, 0, "blocks/acacia_fence_gate.png", 0x8f934f39, false), + + B_188_0_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 0, "blocks/command_block.png", 0x00000000, false), + B_188_1_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 1, "blocks/command_block.png", 0x00000000, false), + B_188_2_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 2, "blocks/command_block.png", 0x00000000, false), + B_188_3_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 3, "blocks/command_block.png", 0x00000000, false), + B_188_4_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 4, "blocks/command_block.png", 0x00000000, false), + B_188_5_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 5, "blocks/command_block.png", 0x00000000, false), + B_188_6_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 6, "blocks/command_block.png", 0x00000000, false), + B_188_7_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 7, "blocks/command_block.png", 0x00000000, false), + B_188_8_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 8, "blocks/command_block.png", 0x00000000, false), + B_188_9_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 9, "blocks/command_block.png", 0x00000000, false), + B_188_10_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 10, "blocks/command_block.png", 0x00000000, false), + B_188_11_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 11, "blocks/command_block.png", 0x00000000, false), + B_188_12_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 12, "blocks/command_block.png", 0x00000000, false), + B_188_13_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 13, "blocks/command_block.png", 0x00000000, false), + B_188_14_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 14, "blocks/command_block.png", 0x00000000, false), + B_188_15_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", null, 188, 15, "blocks/command_block.png", 0x00000000, false), + + B_189_0_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 0, "blocks/command_block.png", 0x00000000, false), + B_189_1_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 1, "blocks/command_block.png", 0x00000000, false), + B_189_2_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 2, "blocks/command_block.png", 0x00000000, false), + B_189_3_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 3, "blocks/command_block.png", 0x00000000, false), + B_189_4_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 4, "blocks/command_block.png", 0x00000000, false), + B_189_5_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 5, "blocks/command_block.png", 0x00000000, false), + B_189_6_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 6, "blocks/command_block.png", 0x00000000, false), + B_189_7_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 7, "blocks/command_block.png", 0x00000000, false), + B_189_8_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 8, "blocks/command_block.png", 0x00000000, false), + B_189_9_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 9, "blocks/command_block.png", 0x00000000, false), + B_189_10_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 10, "blocks/command_block.png", 0x00000000, false), + B_189_11_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 11, "blocks/command_block.png", 0x00000000, false), + B_189_12_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 12, "blocks/command_block.png", 0x00000000, false), + B_189_13_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 13, "blocks/command_block.png", 0x00000000, false), + B_189_14_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 14, "blocks/command_block.png", 0x00000000, false), + B_189_15_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", null, 189, 15, "blocks/command_block.png", 0x00000000, false), + + B_190_0_HARD_GLASS_PANE("minecraft:hard_glass_pane", null, 190, 0, "blocks/glass_pane_top.png", 0x00000000, false), + + B_191_0_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 0, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_1_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 1, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_2_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 2, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_3_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 3, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_4_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 4, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_5_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 5, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_6_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 6, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_7_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 7, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_8_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 8, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_9_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 9, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_10_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 10, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_11_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 11, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_12_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 12, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_13_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 13, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_14_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 14, "blocks/glass_pane_top.png", 0x00000000, false), + B_191_15_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", null, 191, 15, "blocks/glass_pane_top.png", 0x00000000, false), + + B_192_0_CHEMICAL_HEAT("minecraft:chemical_heat", null, 192, 0, "blocks/fire_0.png", 0x00000000, false), + + B_193_0_SPRUCE_DOOR("minecraft:spruce_door", null, 193, 0, "blocks/spruce_door.png", 0xff5a3d0d, false), + B_194_0_BIRCH_DOOR("minecraft:birch_door", null, 194, 0, "blocks/birch_door.png", 0xffdabd8d, false), + B_195_0_JUNGLE_DOOR("minecraft:jungle_door", null, 195, 0, "blocks/jungle_door.png", 0xffBa7d5d, false), + B_196_0_ACACIA_DOOR("minecraft:acacia_door", null, 196, 0, "blocks/acacia_door.png", 0xff934f39, false), + B_197_0_DARK_OAK_DOOR("minecraft:dark_oak_door", null, 197, 0, "blocks/dark_oak_door.png", 0xff2d2213, false), + B_198_0_GRASS_PATH("minecraft:grass_path", null, 198, 0, "blocks/grass_path.png", 0x46a0a0a0, false), + B_199_0_FRAME("minecraft:frame", null, 199, 0, "blocks/frame.png", 0xa04f3e4f, false), + B_200_0_CHORUS_FLOWER("minecraft:chorus_flower", null, 200, 0, "blocks/chorus_flower.png", 0xa0c3b6c8, false), + B_201_0_PURPUR_BLOCK_DEFAULT("minecraft:purpur_block", "default", 201, 0, "blocks/purpur_block_default.png", 0xc095c0ff, false), + B_201_1_PURPUR_BLOCK_CHISELED("minecraft:purpur_block", "chiseled", 201, 1, "blocks/purpur_block_chiseled.png", 0xc095c0ff, false), + B_201_2_PURPUR_BLOCK_LINES("minecraft:purpur_block", "lines", 201, 2, "blocks/purpur_block_lines.png", 0xc095c0ff, false), + B_201_3_PURPUR_BLOCK_DEFAULT("minecraft:purpur_block", "default", 201, 3, "blocks/purpur_block_default.png", 0xc095c0ff, false), + B_203_0_PURPUR_STAIRS("minecraft:purpur_stairs", null, 203, 0, "blocks/purpur_stairs.png", 0xc095c0ff, false), + B_205_0_SHULKERBOX("minecraft:shulker_box", null, 205, 0, "blocks/observer.png", 0xffffffff, false), + B_206_0_END_BRICKS("minecraft:end_bricks", null, 206, 0, "blocks/end_bricks.png", 0xffe7f2af, false), + B_208_0_END_ROD("minecraft:end_rod", null, 208, 0, "blocks/end_rod.png", 0xff6e6e6e, true), + B_209_0_END_GATEWAY("minecraft:end_gateway", null, 209, 0, "blocks/end_gateway.png", 0xff171c27, false), + B_210_0_ALLOW("minecraft:210", null, 210, 0, "blocks/allow.png", 0xff634aba, false), + B_211_0_DENY("minecraft:211", null, 211, 0, "blocks/deny.png", 0xff6ca28a, false), + B_212_0_BORDER_BLOCK("minecraft:212", null, 212, 0, "blocks/border_block.png", 0xff76a7fc, false), + B_213_0_MAGMA_BLOCK("minecraft:magma", "default", 213, 0, "blocks/quartz_block_default.png", 0xffc45a12, false), + B_214_0_NETHERWART_BLOCK("minecraft:nether_wart_block", "default", 214, 0, "blocks/quartz_block_default.png", 0xffbf2030, false), + B_215_0_RED_NETHER_BRICK("minecraft:red_nether_brick", "default", 215, 0, "blocks/quartz_block_default.png", 0xff7f1020, false), + B_216_0_BONE("minecraft:bone_block", "default", 216, 0, "blocks/quartz_block_default.png", 0xffefe5d2, false), + + B_218_0_SHULKERBOX_WHITE("minecraft:shulker_box", "white", 218, 0, "blocks/observer.png", 0xffffffff, false), + B_218_1_SHULKERBOX_ORANGE("minecraft:shulker_box", "orange", 218, 1, "blocks/observer.png", 0xffffd030, false), + B_218_2_SHULKERBOX_MAGENTA("minecraft:shulker_box", "magenta", 218, 2, "blocks/observer.png", 0xffef007f, false), + B_218_3_SHULKERBOX_LIGHT_BLUE("minecraft:shulker_box", "light_blue", 218, 3, "blocks/observer.png", 0xff5588ff, false), + B_218_4_SHULKERBOX_YELLOW("minecraft:shulker_box", "yellow", 218, 4, "blocks/observer.png", 0xffffff40, false), + B_218_5_SHULKERBOX_LIME("minecraft:shulker_box", "lime", 218, 5, "blocks/observer.png", 0xff0db60e, false), + B_218_6_SHULKERBOX_PINK("minecraft:shulker_box", "pink", 218, 6, "blocks/observer.png", 0xffff6076, false), + B_218_7_SHULKERBOX_GRAY("minecraft:shulker_box", "gray", 218, 7, "blocks/observer.png", 0xff565656, false), + B_218_8_SHULKERBOX_SILVER("minecraft:shulker_box", "silver", 218, 8, "blocks/observer.png", 0xffa6a6a6, false), + B_218_9_SHULKERBOX_CYAN("minecraft:shulker_box", "cyan", 218, 9, "blocks/observer.png", 0xff0d5656, false), + B_218_10_SHULKERBOX_PURPLE("minecraft:shulker_box", "purple", 218, 10, "blocks/observer.png", 0xff560d56, false), + B_218_11_SHULKERBOX_BLUE("minecraft:shulker_box", "blue", 218, 11, "blocks/observer.png", 0xff0d0e56, false), + B_218_12_SHULKERBOX_BROWN("minecraft:shulker_box", "brown", 218, 12, "blocks/observer.png", 0xff804530, false), + B_218_13_SHULKERBOX_GREEN("minecraft:shulker_box", "green", 218, 13, "blocks/observer.png", 0xff0d560e, false), + B_218_14_SHULKERBOX_RED("minecraft:shulker_box", "red", 218, 14, "blocks/observer.png", 0xffff2020, false), + B_218_15_SHULKERBOX_BLACK("minecraft:shulker_box", "black", 218, 15, "blocks/observer.png", 0xff000000, false), + + B_219_2_GLAZED_TERRACOTTA_PURPLE("minecraft:purple_glazed_terracotta", "purple", 219, 2, "blocks/observer.png", 0xff762d76, false), + B_219_3_GLAZED_TERRACOTTA_PURPLE("minecraft:purple_glazed_terracotta", "purple", 219, 3, "blocks/observer.png", 0xff762d76, false), + B_219_4_GLAZED_TERRACOTTA_PURPLE("minecraft:purple_glazed_terracotta", "purple", 219, 4, "blocks/observer.png", 0xff762d76, false), + B_219_5_GLAZED_TERRACOTTA_PURPLE("minecraft:purple_glazed_terracotta", "purple", 219, 5, "blocks/observer.png", 0xff762d76, false), + B_220_2_GLAZED_TERRACOTTA_WHITE("minecraft:white_glazed_terracotta", "white", 220, 2, "blocks/observer.png", 0xffffffff, false), + B_220_3_GLAZED_TERRACOTTA_WHITE("minecraft:white_glazed_terracotta", "white", 220, 3, "blocks/observer.png", 0xffffffff, false), + B_220_4_GLAZED_TERRACOTTA_WHITE("minecraft:white_glazed_terracotta", "white", 220, 4, "blocks/observer.png", 0xffffffff, false), + B_220_5_GLAZED_TERRACOTTA_WHITE("minecraft:white_glazed_terracotta", "white", 220, 5, "blocks/observer.png", 0xffffffff, false), + B_221_2_GLAZED_TERRACOTTA_ORANGE("minecraft:orange_glazed_terracotta", "orange", 221, 2, "blocks/observer.png", 0xffff8030, false), + B_221_3_GLAZED_TERRACOTTA_ORANGE("minecraft:orange_glazed_terracotta", "orange", 221, 3, "blocks/observer.png", 0xffff8030, false), + B_221_4_GLAZED_TERRACOTTA_ORANGE("minecraft:orange_glazed_terracotta", "orange", 221, 4, "blocks/observer.png", 0xffff8030, false), + B_221_5_GLAZED_TERRACOTTA_ORANGE("minecraft:orange_glazed_terracotta", "orange", 221, 5, "blocks/observer.png", 0xffff8030, false), + B_222_2_GLAZED_TERRACOTTA_LIGHT_MAGENTA("minecraft:magenta_glazed_terracotta", "magenta", 222, 2, "blocks/observer.png", 0xffff108f, false), + B_222_3_GLAZED_TERRACOTTA_LIGHT_MAGENTA("minecraft:magenta_glazed_terracotta", "magenta", 222, 3, "blocks/observer.png", 0xffff108f, false), + B_222_4_GLAZED_TERRACOTTA_LIGHT_MAGENTA("minecraft:magenta_glazed_terracotta", "magenta", 222, 4, "blocks/observer.png", 0xffff108f, false), + B_222_5_GLAZED_TERRACOTTA_LIGHT_MAGENTA("minecraft:magenta_glazed_terracotta", "magenta", 222, 5, "blocks/observer.png", 0xffff108f, false), + B_223_2_GLAZED_TERRACOTTA_LIGHT_BLUE("minecraft:light_blue_glazed_terracotta", "light_blue", 223, 2, "blocks/observer.png", 0xff75a8ff, false), + B_223_3_GLAZED_TERRACOTTA_LIGHT_BLUE("minecraft:light_blue_glazed_terracotta", "light_blue", 223, 3, "blocks/observer.png", 0xff75a8ff, false), + B_223_4_GLAZED_TERRACOTTA_LIGHT_BLUE("minecraft:light_blue_glazed_terracotta", "light_blue", 223, 4, "blocks/observer.png", 0xff75a8ff, false), + B_223_5_GLAZED_TERRACOTTA_LIGHT_BLUE("minecraft:light_blue_glazed_terracotta", "light_blue", 223, 5, "blocks/observer.png", 0xff75a8ff, false), + B_224_2_GLAZED_TERRACOTTA_YELLOW("minecraft:yellow_glazed_terracotta", "yellow", 224, 2, "blocks/observer.png", 0xffffff60, false), + B_224_3_GLAZED_TERRACOTTA_YELLOW("minecraft:yellow_glazed_terracotta", "yellow", 224, 3, "blocks/observer.png", 0xffffff60, false), + B_224_4_GLAZED_TERRACOTTA_YELLOW("minecraft:yellow_glazed_terracotta", "yellow", 224, 4, "blocks/observer.png", 0xffffff60, false), + B_224_5_GLAZED_TERRACOTTA_YELLOW("minecraft:yellow_glazed_terracotta", "yellow", 224, 5, "blocks/observer.png", 0xffffff60, false), + B_225_2_GLAZED_TERRACOTTA_LIME("minecraft:lime_glazed_terracotta", "lime", 225, 2, "blocks/observer.png", 0xff2dd62e, false), + B_225_3_GLAZED_TERRACOTTA_LIME("minecraft:lime_glazed_terracotta", "lime", 225, 3, "blocks/observer.png", 0xff2dd62e, false), + B_225_4_GLAZED_TERRACOTTA_LIME("minecraft:lime_glazed_terracotta", "lime", 225, 4, "blocks/observer.png", 0xff2dd62e, false), + B_225_5_GLAZED_TERRACOTTA_LIME("minecraft:lime_glazed_terracotta", "lime", 225, 5, "blocks/observer.png", 0xff2dd62e, false), + B_226_2_GLAZED_TERRACOTTA_PINK("minecraft:pink_glazed_terracotta", "pink", 226, 2, "blocks/observer.png", 0xffff8096, false), + B_226_3_GLAZED_TERRACOTTA_PINK("minecraft:pink_glazed_terracotta", "pink", 226, 3, "blocks/observer.png", 0xffff8096, false), + B_226_4_GLAZED_TERRACOTTA_PINK("minecraft:pink_glazed_terracotta", "pink", 226, 4, "blocks/observer.png", 0xffff8096, false), + B_226_5_GLAZED_TERRACOTTA_PINK("minecraft:pink_glazed_terracotta", "pink", 226, 5, "blocks/observer.png", 0xffff8096, false), + B_227_2_GLAZED_TERRACOTTA_GRAY("minecraft:gray_glazed_terracotta", "gray", 227, 2, "blocks/observer.png", 0xff767676, false), + B_227_3_GLAZED_TERRACOTTA_GRAY("minecraft:gray_glazed_terracotta", "gray", 227, 3, "blocks/observer.png", 0xff767676, false), + B_227_4_GLAZED_TERRACOTTA_GRAY("minecraft:gray_glazed_terracotta", "gray", 227, 4, "blocks/observer.png", 0xff767676, false), + B_227_5_GLAZED_TERRACOTTA_GRAY("minecraft:gray_glazed_terracotta", "gray", 227, 5, "blocks/observer.png", 0xff767676, false), + B_228_2_GLAZED_TERRACOTTA_LIGHT_GRAY("minecraft:silver_glazed_terracotta", "silver", 228, 2, "blocks/observer.png", 0xffc6c6c6, false), + B_228_3_GLAZED_TERRACOTTA_LIGHT_GRAY("minecraft:silver_glazed_terracotta", "silver", 228, 3, "blocks/observer.png", 0xffc6c6c6, false), + B_228_4_GLAZED_TERRACOTTA_LIGHT_GRAY("minecraft:silver_glazed_terracotta", "silver", 228, 4, "blocks/observer.png", 0xffc6c6c6, false), + B_228_5_GLAZED_TERRACOTTA_LIGHT_GRAY("minecraft:silver_glazed_terracotta", "silver", 228, 5, "blocks/observer.png", 0xffc6c6c6, false), + B_229_2_GLAZED_TERRACOTTA_CYAN("minecraft:cyan_glazed_terracotta", "cyan", 229, 2, "blocks/observer.png", 0xff2d7676, false), + B_229_3_GLAZED_TERRACOTTA_CYAN("minecraft:cyan_glazed_terracotta", "cyan", 229, 3, "blocks/observer.png", 0xff2d7676, false), + B_229_4_GLAZED_TERRACOTTA_CYAN("minecraft:cyan_glazed_terracotta", "cyan", 229, 4, "blocks/observer.png", 0xff2d7676, false), + B_229_5_GLAZED_TERRACOTTA_CYAN("minecraft:cyan_glazed_terracotta", "cyan", 229, 5, "blocks/observer.png", 0xff2d7676, false), + B_230_0_CHALKBOARD("minecraft:230", null, 230, 0, "blocks/chalkboard.png", 0xff3d6e86, false), + B_231_2_GLAZED_TERRACOTTA_BLUE("minecraft:blue_glazed_terracotta", "blue", 231, 2, "blocks/observer.png", 0xff2d2e76, false), + B_231_3_GLAZED_TERRACOTTA_BLUE("minecraft:blue_glazed_terracotta", "blue", 231, 3, "blocks/observer.png", 0xff2d2e76, false), + B_231_4_GLAZED_TERRACOTTA_BLUE("minecraft:blue_glazed_terracotta", "blue", 231, 4, "blocks/observer.png", 0xff2d2e76, false), + B_231_5_GLAZED_TERRACOTTA_BLUE("minecraft:blue_glazed_terracotta", "blue", 231, 5, "blocks/observer.png", 0xff2d2e76, false), + B_232_2_GLAZED_TERRACOTTA_BROWN("minecraft:brown_glazed_terracotta", "brown", 232, 2, "blocks/observer.png", 0xffa06550, false), + B_232_3_GLAZED_TERRACOTTA_BROWN("minecraft:brown_glazed_terracotta", "brown", 232, 3, "blocks/observer.png", 0xffa06550, false), + B_232_4_GLAZED_TERRACOTTA_BROWN("minecraft:brown_glazed_terracotta", "brown", 232, 4, "blocks/observer.png", 0xffa06550, false), + B_232_5_GLAZED_TERRACOTTA_BROWN("minecraft:brown_glazed_terracotta", "brown", 232, 5, "blocks/observer.png", 0xffa06550, false), + B_233_2_GLAZED_TERRACOTTA_GREEN("minecraft:green_glazed_terracotta", "green", 233, 2, "blocks/observer.png", 0xff2d762e, false), + B_233_3_GLAZED_TERRACOTTA_GREEN("minecraft:green_glazed_terracotta", "green", 233, 3, "blocks/observer.png", 0xff2d762e, false), + B_233_4_GLAZED_TERRACOTTA_GREEN("minecraft:green_glazed_terracotta", "green", 233, 4, "blocks/observer.png", 0xff2d762e, false), + B_233_5_GLAZED_TERRACOTTA_GREEN("minecraft:green_glazed_terracotta", "green", 233, 5, "blocks/observer.png", 0xff2d762e, false), + B_234_2_GLAZED_TERRACOTTA_RED("minecraft:red_glazed_terracotta", "red", 234, 2, "blocks/observer.png", 0xffff3030, false), + B_234_3_GLAZED_TERRACOTTA_RED("minecraft:red_glazed_terracotta", "red", 234, 3, "blocks/observer.png", 0xffff3030, false), + B_234_4_GLAZED_TERRACOTTA_RED("minecraft:red_glazed_terracotta", "red", 234, 4, "blocks/observer.png", 0xffff3030, false), + B_234_5_GLAZED_TERRACOTTA_RED("minecraft:red_glazed_terracotta", "red", 234, 5, "blocks/observer.png", 0xffff3030, false), + B_235_2_GLAZED_TERRACOTTA_BLACK("minecraft:black_glazed_terracotta", "black", 235, 2, "blocks/observer.png", 0xff050505, false), + B_235_3_GLAZED_TERRACOTTA_BLACK("minecraft:black_glazed_terracotta", "black", 235, 3, "blocks/observer.png", 0xff050505, false), + B_235_4_GLAZED_TERRACOTTA_BLACK("minecraft:black_glazed_terracotta", "black", 235, 4, "blocks/observer.png", 0xff050505, false), + B_235_5_GLAZED_TERRACOTTA_BLACK("minecraft:black_glazed_terracotta", "black", 235, 5, "blocks/observer.png", 0xff050505, false), + + B_236_0_CONCRETE_WHITE("minecraft:concrete", "orange", 236, 0, "blocks/observer.png", 0xffffffff, false), + B_236_1_CONCRETE_ORANGE("minecraft:concrete", "orange", 236, 1, "blocks/observer.png", 0xffffd030, false), + B_236_2_CONCRETE_MAGENTA("minecraft:concrete", "magenta", 236, 2, "blocks/observer.png", 0xffef007f, false), + B_236_3_CONCRETE_LIGHT_BLUE("minecraft:concrete", "light_blue", 236, 3, "blocks/observer.png", 0xff5588ff, false), + B_236_4_CONCRETE_YELLOW("minecraft:concrete", "yellow", 236, 4, "blocks/observer.png", 0xffffff40, false), + B_236_5_CONCRETE_LIME("minecraft:concrete", "lime", 236, 5, "blocks/observer.png", 0xff0db60e, false), + B_236_6_CONCRETE_PINK("minecraft:concrete", "pink", 236, 6, "blocks/observer.png", 0xffff6076, false), + B_236_7_CONCRETE_GRAY("minecraft:concrete", "gray", 236, 7, "blocks/observer.png", 0xff565656, false), + B_236_8_CONCRETE_SILVER("minecraft:concrete", "silver", 236, 8, "blocks/observer.png", 0xffa6a6a6, false), + B_236_9_CONCRETE_CYAN("minecraft:concrete", "cyan", 236, 9, "blocks/observer.png", 0xff0d5656, false), + B_236_10_CONCRETE_PURPLE("minecraft:concrete", "purple", 236, 10, "blocks/observer.png", 0xff560d56, false), + B_236_11_CONCRETE_BLUE("minecraft:concrete", "blue", 236, 11, "blocks/observer.png", 0xff0d0e56, false), + B_236_12_CONCRETE_BROWN("minecraft:concrete", "brown", 236, 12, "blocks/observer.png", 0xff804530, false), + B_236_13_CONCRETE_GREEN("minecraft:concrete", "green", 236, 13, "blocks/observer.png", 0xff0d560e, false), + B_236_14_CONCRETE_RED("minecraft:concrete", "red", 236, 14, "blocks/observer.png", 0xffff2020, false), + B_236_15_CONCRETE_BLACK("minecraft:concrete", "black", 236, 15, "blocks/observer.png", 0xff000000, false), + + B_237_0_CONCRETE_POWDER_WHITE("minecraft:concretePowder", "white", 237, 0, "blocks/observer.png", 0xffffffff, false), + B_237_1_CONCRETE_POWDER_ORANGE("minecraft:concretePowder", "orange", 237, 1, "blocks/observer.png", 0xffffd030, false), + B_237_2_CONCRETE_POWDER_MAGENTA("minecraft:concretePowder", "magenta", 237, 2, "blocks/observer.png", 0xffef007f, false), + B_237_3_CONCRETE_POWDER_LIGHT_BLUE("minecraft:concretePowder", "light_blue", 237, 3, "blocks/observer.png", 0xff5588ff, false), + B_237_4_CONCRETE_POWDER_YELLOW("minecraft:concretePowder", "yellow", 237, 4, "blocks/observer.png", 0xffffff40, false), + B_237_5_CONCRETE_POWDER_LIME("minecraft:concretePowder", "lime", 237, 5, "blocks/observer.png", 0xff0db60e, false), + B_237_6_CONCRETE_POWDER_PINK("minecraft:concretePowder", "pink", 237, 6, "blocks/observer.png", 0xffff6076, false), + B_237_7_CONCRETE_POWDER_GRAY("minecraft:concretePowder", "gray", 237, 7, "blocks/observer.png", 0xff565656, false), + B_237_8_CONCRETE_POWDER_SILVER("minecraft:concretePowder", "silver", 237, 8, "blocks/observer.png", 0xffa6a6a6, false), + B_237_9_CONCRETE_POWDER_CYAN("minecraft:concretePowder", "cyan", 237, 9, "blocks/observer.png", 0xff0d5656, false), + B_237_10_CONCRETE_POWDER_PURPLE("minecraft:concretePowder", "purple", 237, 10, "blocks/observer.png", 0xff560d56, false), + B_237_11_CONCRETE_POWDER_BLUE("minecraft:concretePowder", "blue", 237, 11, "blocks/observer.png", 0xff0d0e56, false), + B_237_12_CONCRETE_POWDER_BROWN("minecraft:concretePowder", "brown", 237, 12, "blocks/observer.png", 0xff804530, false), + B_237_13_CONCRETE_POWDER_GREEN("minecraft:concretePowder", "green", 237, 13, "blocks/observer.png", 0xff0d560e, false), + B_237_14_CONCRETE_POWDER_RED("minecraft:concretePowder", "brown", 237, 14, "blocks/observer.png", 0xffff2020, false), + B_237_15_CONCRETE_POWDER_BLACK("minecraft:concretePowder", "black", 237, 15, "blocks/observer.png", 0xff000000, false), + + B_238_0_CHEMISTRY_TABLE("minecraft:chemistry_table", "orange", 238, 0, "blocks/observer.png", 0xffffffff, false), + B_238_1_CHEMISTRY_TABLE("minecraft:chemistry_table", "orange", 238, 1, "blocks/observer.png", 0xffffd030, false), + B_238_2_CHEMISTRY_TABLE("minecraft:chemistry_table", "magenta", 238, 2, "blocks/observer.png", 0xffef007f, false), + B_238_3_CHEMISTRY_TABLE("minecraft:chemistry_table", "light_blue", 238, 3, "blocks/observer.png", 0xff5588ff, false), + B_238_4_CHEMISTRY_TABLE("minecraft:chemistry_table", "yellow", 238, 4, "blocks/observer.png", 0xffffff40, false), + B_238_5_CHEMISTRY_TABLE("minecraft:chemistry_table", "lime", 238, 5, "blocks/observer.png", 0xff0db60e, false), + B_238_6_CHEMISTRY_TABLE("minecraft:chemistry_table", "pink", 238, 6, "blocks/observer.png", 0xffff6076, false), + B_238_7_CHEMISTRY_TABLE("minecraft:chemistry_table", "gray", 238, 7, "blocks/observer.png", 0xff565656, false), + B_238_8_CHEMISTRY_TABLE("minecraft:chemistry_table", "silver", 238, 8, "blocks/observer.png", 0xffa6a6a6, false), + B_238_9_CHEMISTRY_TABLE("minecraft:chemistry_table", "cyan", 238, 9, "blocks/observer.png", 0xff0d5656, false), + B_238_10_CHEMISTRY_TABLE("minecraft:chemistry_table", "purple", 238, 10, "blocks/observer.png", 0xff560d56, false), + B_238_11_CHEMISTRY_TABLE("minecraft:chemistry_table", "blue", 238, 11, "blocks/observer.png", 0xff0d0e56, false), + B_238_12_CHEMISTRY_TABLE("minecraft:chemistry_table", "brown", 238, 12, "blocks/observer.png", 0xff804530, false), + B_238_13_CHEMISTRY_TABLE("minecraft:chemistry_table", "green", 238, 13, "blocks/observer.png", 0xff0d560e, false), + B_238_14_CHEMISTRY_TABLE("minecraft:chemistry_table", "brown", 238, 14, "blocks/observer.png", 0xffff2020, false), + B_238_15_CHEMISTRY_TABLE("minecraft:chemistry_table", "black", 238, 15, "blocks/observer.png", 0xff000000, false), + + B_239_0_UNDERWATER_TORCH("minecraft:underwater_torch", "orange", 239, 0, "blocks/observer.png", 0xffffffff, false), + B_239_1_UNDERWATER_TORCH("minecraft:underwater_torch", "orange", 239, 1, "blocks/observer.png", 0xffffd030, false), + B_239_2_UNDERWATER_TORCH("minecraft:underwater_torch", "magenta", 239, 2, "blocks/observer.png", 0xffef007f, false), + B_239_3_UNDERWATER_TORCH("minecraft:underwater_torch", "light_blue", 239, 3, "blocks/observer.png", 0xff5588ff, false), + B_239_4_UNDERWATER_TORCH("minecraft:underwater_torch", "yellow", 239, 4, "blocks/observer.png", 0xffffff40, false), + B_239_5_UNDERWATER_TORCH("minecraft:underwater_torch", "lime", 239, 5, "blocks/observer.png", 0xff0db60e, false), + B_239_6_UNDERWATER_TORCH("minecraft:underwater_torch", "pink", 239, 6, "blocks/observer.png", 0xffff6076, false), + B_239_7_UNDERWATER_TORCH("minecraft:underwater_torch", "gray", 239, 7, "blocks/observer.png", 0xff565656, false), + + B_240_0_CHORUS_PLANT("minecraft:chorus_plant", null, 240, 0, "blocks/chorus_plant.png", 0xaa3d6e86, false), + B_241_0_STAINED_GLASS_WHITE("minecraft:stained_glass", "white", 241, 0, "blocks/stained_glass_white.png", 0x50836f64, false), + B_241_1_STAINED_GLASS_ORANGE("minecraft:stained_glass", "orange", 241, 1, "blocks/stained_glass_orange.png", 0x509d5021, false), + B_241_2_STAINED_GLASS_MAGENTA("minecraft:stained_glass", "magenta", 241, 2, "blocks/stained_glass_magenta.png", 0x50915369, false), + B_241_3_STAINED_GLASS_LIGHT_BLUE("minecraft:stained_glass", "light_blue", 241, 3, "blocks/stained_glass_light_blue.png", 0x50706b87, false), + B_241_4_STAINED_GLASS_YELLOW("minecraft:stained_glass", "yellow", 241, 4, "blocks/stained_glass_yellow.png", 0x50b5801f, false), + B_241_5_STAINED_GLASS_LIME("minecraft:stained_glass", "lime", 241, 5, "blocks/stained_glass_lime.png", 0x50617030, false), + B_241_6_STAINED_GLASS_PINK("minecraft:stained_glass", "pink", 241, 6, "blocks/stained_glass_pink.png", 0x509c4848, false), + B_241_7_STAINED_GLASS_GRAY("minecraft:stained_glass", "gray", 241, 7, "blocks/stained_glass_gray.png", 0x50392721, false), + B_241_8_STAINED_GLASS_SILVER("minecraft:stained_glass", "silver", 241, 8, "blocks/stained_glass_silver.png", 0x5081655b, false), + B_241_9_STAINED_GLASS_CYAN("minecraft:stained_glass", "cyan", 241, 9, "blocks/stained_glass_cyan.png", 0x50565959, false), + B_241_10_STAINED_GLASS_PURPLE("minecraft:stained_glass", "purple", 241, 10, "blocks/stained_glass_purple.png", 0x50744555, false), + B_241_11_STAINED_GLASS_BLUE("minecraft:stained_glass", "blue", 241, 11, "blocks/stained_glass_blue.png", 0x50463857, false), + B_241_12_STAINED_GLASS_BROWN("minecraft:stained_glass", "brown", 241, 12, "blocks/stained_glass_brown.png", 0x50492e1f, false), + B_241_13_STAINED_GLASS_GREEN("minecraft:stained_glass", "green", 241, 13, "blocks/stained_glass_green.png", 0x50484f26, false), + B_241_14_STAINED_GLASS_RED("minecraft:stained_glass", "red", 241, 14, "blocks/stained_glass_red.png", 0x50ff382b, false), + B_241_15_STAINED_GLASS_BLACK("minecraft:stained_glass", "black", 241, 15, "blocks/stained_glass_black.png", 0x5021120d, false), + B_242_0_CAMERA("minecraft:242", null, 242, 0, "blocks/camera.png", 0xff3d6e86, false), + B_243_0_PODZOL("minecraft:podzol", null, 243, 0, "blocks/podzol.png", 0xff533a1b, true), + B_244_0_BEETROOT("minecraft:beetroot", null, 244, 0, "blocks/beetroot.png", 0x0901ab10, false), + B_245_0_STONECUTTER("minecraft:stonecutter", null, 245, 0, "blocks/stonecutter.png", 0xff515151, false), + B_246_0_GLOWINGOBSIDIAN("minecraft:glowingobsidian", null, 246, 0, "blocks/glowingobsidian.png", 0xff17060a, false), + B_247_0_NETHERREACTOR_DEFAULT("minecraft:netherreactor", "default", 247, 0, "blocks/netherreactor_default.png", 0xffd2d200, false), + B_247_1_NETHERREACTOR_ACTIVE("minecraft:netherreactor", "active", 247, 1, "blocks/netherreactor_active.png", 0xff3d6e86, false), + B_247_2_NETHERREACTOR_COOLED("minecraft:netherreactor", "cooled", 247, 2, "blocks/netherreactor_cooled.png", 0xff3d6e86, false), + B_248_0_INFO_UPDATE("minecraft:info_update", null, 248, 0, "blocks/info_update.png", 0xff2f3218, false), + B_249_0_INFO_UPDATE2("minecraft:info_update2", null, 249, 0, "blocks/info_update2.png", 0xff2f3218, false), + B_250_0_MOVINGBLOCK("minecraft:movingBlock", null, 250, 0, "blocks/movingBlock.png", 0, false), + + B_251_0_OBSERVER("minecraft:observer", null, 251, 0, "blocks/observer.png", 0xff3d6e86, false), + B_251_1_OBSERVER("minecraft:observer", null, 251, 1, "blocks/observer.png", 0xff3d6e86, false), + B_251_2_OBSERVER("minecraft:observer", null, 251, 2, "blocks/observer.png", 0xff3d6e86, false), + B_251_3_OBSERVER("minecraft:observer", null, 251, 3, "blocks/observer.png", 0xff3d6e86, false), + B_251_4_OBSERVER("minecraft:observer", null, 251, 4, "blocks/observer.png", 0xff3d6e86, false), + B_251_5_OBSERVER("minecraft:observer", null, 251, 5, "blocks/observer.png", 0xff3d6e86, false), + B_251_6_OBSERVER("minecraft:observer", null, 251, 6, "blocks/observer.png", 0xff3d6e86, false), + B_251_7_OBSERVER("minecraft:observer", null, 251, 7, "blocks/observer.png", 0xff3d6e86, false), + B_251_8_OBSERVER("minecraft:observer", null, 251, 8, "blocks/observer.png", 0xff3d6e86, false), + B_251_9_OBSERVER("minecraft:observer", null, 251, 9, "blocks/observer.png", 0xff3d6e86, false), + B_251_10_OBSERVER("minecraft:observer", null, 251, 10, "blocks/observer.png", 0xff3d6e86, false), + B_251_11_OBSERVER("minecraft:observer", null, 251, 11, "blocks/observer.png", 0xff3d6e86, false), + B_251_12_OBSERVER("minecraft:observer", null, 251, 12, "blocks/observer.png", 0xff3d6e86, false), + B_251_13_OBSERVER("minecraft:observer", null, 251, 13, "blocks/observer.png", 0xff3d6e86, false), + B_251_14_OBSERVER("minecraft:observer", null, 251, 14, "blocks/observer.png", 0xff3d6e86, false), + B_251_15_OBSERVER("minecraft:observer", null, 251, 15, "blocks/observer.png", 0xff3d6e86, false), + + B_252_0_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 0, "blocks/observer.png", 0xff3d6e86, false), + B_252_1_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 1, "blocks/observer.png", 0xff3d6e86, false), + B_252_2_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 2, "blocks/observer.png", 0xff3d6e86, false), + B_252_3_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 3, "blocks/observer.png", 0xff3d6e86, false), + B_252_4_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 4, "blocks/observer.png", 0xff3d6e86, false), + B_252_5_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 5, "blocks/observer.png", 0xff3d6e86, false), + B_252_6_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 6, "blocks/observer.png", 0xff3d6e86, false), + B_252_7_STRUCTURE_BLOCK("minecraft:structure_block", null, 252, 7, "blocks/observer.png", 0xff3d6e86, false), + + B_253_0_HARD_GLASS("minecraft:hard_glass", null, 253, 0, "blocks/observer.png", 0xff3d6e86, false), + + B_254_0_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "white", 254, 0, "blocks/stained_glass_white.png", 0x50836f64, false), + B_254_1_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "orange", 254, 1, "blocks/stained_glass_orange.png", 0x509d5021, false), + B_254_2_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "magenta", 254, 2, "blocks/stained_glass_magenta.png", 0x50915369, false), + B_254_3_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "light_blue", 254, 3, "blocks/stained_glass_light_blue.png", 0x50706b87, false), + B_254_4_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "yellow", 254, 4, "blocks/stained_glass_yellow.png", 0x50b5801f, false), + B_254_5_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "lime", 254, 5, "blocks/stained_glass_lime.png", 0x50617030, false), + B_254_6_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "pink", 254, 6, "blocks/stained_glass_pink.png", 0x509c4848, false), + B_254_7_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "gray", 254, 7, "blocks/stained_glass_gray.png", 0x50392721, false), + B_254_8_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "silver", 254, 8, "blocks/stained_glass_silver.png", 0x5081655b, false), + B_254_9_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "cyan", 254, 9, "blocks/stained_glass_cyan.png", 0x50565959, false), + B_254_10_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "purple", 254, 10, "blocks/stained_glass_purple.png", 0x50744555, false), + B_254_11_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "blue", 254, 11, "blocks/stained_glass_blue.png", 0x50463857, false), + B_254_12_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "brown", 254, 12, "blocks/stained_glass_brown.png", 0x50492e1f, false), + B_254_13_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "green", 254, 13, "blocks/stained_glass_green.png", 0x50484f26, false), + B_254_14_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "red", 254, 14, "blocks/stained_glass_red.png", 0x50ff382b, false), + B_254_15_HARD_STAINED_GLASS("minecraft:hard_stained_glass", "black", 254, 15, "blocks/stained_glass_black.png", 0x5021120d, false), + + B_255_0_RESERVED6("minecraft:reserved6", null, 255, 0, "blocks/reserved6.png", 0xff19171a, false), + + B_2153_0_256("minecraft:256", "", 2153, 0, "blocks/observer.png", 0xff3d6e86, false), + B_2154_0_prismarine_stairs("minecraft:prismarine_stairs", "", 2154, 0, "blocks/observer.png", 0xA9498d6e, false), + B_2155_1_prismarine_stairs("minecraft:prismarine_stairs", "", 2155, 1, "blocks/observer.png", 0xA9498d6e, false), + B_2156_2_prismarine_stairs("minecraft:prismarine_stairs", "", 2156, 2, "blocks/observer.png", 0xA9498d6e, false), + B_2157_3_prismarine_stairs("minecraft:prismarine_stairs", "", 2157, 3, "blocks/observer.png", 0xA9498d6e, false), + B_2158_4_prismarine_stairs("minecraft:prismarine_stairs", "", 2158, 4, "blocks/observer.png", 0xA9498d6e, false), + B_2159_5_prismarine_stairs("minecraft:prismarine_stairs", "", 2159, 5, "blocks/observer.png", 0xA9498d6e, false), + B_2160_6_prismarine_stairs("minecraft:prismarine_stairs", "", 2160, 6, "blocks/observer.png", 0xA9498d6e, false), + B_2161_7_prismarine_stairs("minecraft:prismarine_stairs", "", 2161, 7, "blocks/observer.png", 0xA9498d6e, false), + B_2162_0_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2162, 0, "blocks/observer.png", 0xff04635e, false), + B_2163_1_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2163, 1, "blocks/observer.png", 0xff04635e, false), + B_2164_2_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2164, 2, "blocks/observer.png", 0xff04635e, false), + B_2165_3_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2165, 3, "blocks/observer.png", 0xff04635e, false), + B_2166_4_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2166, 4, "blocks/observer.png", 0xff04635e, false), + B_2167_5_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2167, 5, "blocks/observer.png", 0xff04635e, false), + B_2168_6_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2168, 6, "blocks/observer.png", 0xff04635e, false), + B_2169_7_dark_prismarine_stairs("minecraft:dark_prismarine_stairs", "", 2169, 7, "blocks/observer.png", 0xff04635e, false), + B_2170_0_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2170, 0, "blocks/observer.png", 0xff097d6e, false), + B_2171_1_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2171, 1, "blocks/observer.png", 0xff097d6e, false), + B_2172_2_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2172, 2, "blocks/observer.png", 0xff097d6e, false), + B_2173_3_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2173, 3, "blocks/observer.png", 0xff097d6e, false), + B_2174_4_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2174, 4, "blocks/observer.png", 0xff097d6e, false), + B_2175_5_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2175, 5, "blocks/observer.png", 0xff097d6e, false), + B_2176_6_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2176, 6, "blocks/observer.png", 0xff097d6e, false), + B_2177_7_prismarine_bricks_stairs("minecraft:prismarine_bricks_stairs", "", 2177, 7, "blocks/observer.png", 0xff097d6e, false), + B_2178_0_stripped_spruce_log("minecraft:stripped_spruce_log", "", 2178, 0, "blocks/observer.png", 0xff5a3d0d, false), + B_2179_1_stripped_spruce_log("minecraft:stripped_spruce_log", "", 2179, 1, "blocks/observer.png", 0xff5a3d0d, false), + B_2180_2_stripped_spruce_log("minecraft:stripped_spruce_log", "", 2180, 2, "blocks/observer.png", 0xff5a3d0d, false), + B_2181_3_stripped_spruce_log("minecraft:stripped_spruce_log", "", 2181, 3, "blocks/observer.png", 0xff5a3d0d, false), + B_2182_0_stripped_birch_log("minecraft:stripped_birch_log", "", 2182, 0, "blocks/observer.png", 0xffdabd8d, false), + B_2183_1_stripped_birch_log("minecraft:stripped_birch_log", "", 2183, 1, "blocks/observer.png", 0xffdabd8d, false), + B_2184_2_stripped_birch_log("minecraft:stripped_birch_log", "", 2184, 2, "blocks/observer.png", 0xffdabd8d, false), + B_2185_3_stripped_birch_log("minecraft:stripped_birch_log", "", 2185, 3, "blocks/observer.png", 0xffdabd8d, false), + B_2186_0_stripped_jungle_log("minecraft:stripped_jungle_log", "", 2186, 0, "blocks/observer.png", 0xffBa7d5d, false), + B_2187_1_stripped_jungle_log("minecraft:stripped_jungle_log", "", 2187, 1, "blocks/observer.png", 0xffBa7d5d, false), + B_2188_2_stripped_jungle_log("minecraft:stripped_jungle_log", "", 2188, 2, "blocks/observer.png", 0xffBa7d5d, false), + B_2189_3_stripped_jungle_log("minecraft:stripped_jungle_log", "", 2189, 3, "blocks/observer.png", 0xffBa7d5d, false), + B_2190_0_stripped_acacia_log("minecraft:stripped_acacia_log", "", 2190, 0, "blocks/observer.png", 0xff934f39, false), + B_2191_1_stripped_acacia_log("minecraft:stripped_acacia_log", "", 2191, 1, "blocks/observer.png", 0xff934f39, false), + B_2192_2_stripped_acacia_log("minecraft:stripped_acacia_log", "", 2192, 2, "blocks/observer.png", 0xff934f39, false), + B_2193_3_stripped_acacia_log("minecraft:stripped_acacia_log", "", 2193, 3, "blocks/observer.png", 0xff934f39, false), + B_2194_0_stripped_dark_oak_log("minecraft:stripped_dark_oak_log", "", 2194, 0, "blocks/observer.png", 0xff2d2213, false), + B_2195_1_stripped_dark_oak_log("minecraft:stripped_dark_oak_log", "", 2195, 1, "blocks/observer.png", 0xff2d2213, false), + B_2196_2_stripped_dark_oak_log("minecraft:stripped_dark_oak_log", "", 2196, 2, "blocks/observer.png", 0xff2d2213, false), + B_2197_3_stripped_dark_oak_log("minecraft:stripped_dark_oak_log", "", 2197, 3, "blocks/observer.png", 0xff2d2213, false), + B_2198_0_stripped_oak_log("minecraft:stripped_oak_log", "", 2198, 0, "blocks/observer.png", 0xff9a7d4d, false), + B_2199_1_stripped_oak_log("minecraft:stripped_oak_log", "", 2199, 1, "blocks/observer.png", 0xff9a7d4d, false), + B_2200_2_stripped_oak_log("minecraft:stripped_oak_log", "", 2200, 2, "blocks/observer.png", 0xff9a7d4d, false), + B_2201_3_stripped_oak_log("minecraft:stripped_oak_log", "", 2201, 3, "blocks/observer.png", 0xff9a7d4d, false), + B_2202_0_blue_ice("minecraft:blue_ice", "", 2202, 0, "blocks/observer.png", 0xff7dbeF6, false), + /**/ + B_4091_0_seagrass("minecraft:seagrass", "", 4091, 0, "blocks/observer.png", 0x4e787878, false), + B_4092_1_seagrass("minecraft:seagrass", "", 4092, 1, "blocks/observer.png", 0x4e787878, false), + B_4093_2_seagrass("minecraft:seagrass", "", 4093, 2, "blocks/observer.png", 0x4e787878, false), + B_4094_3_seagrass("minecraft:seagrass", "", 4094, 3, "blocks/observer.png", 0x4e787878, false), + B_4095_0_coral("minecraft:coral", "", 4095, 0, "blocks/observer.png", 0xff3d6e86, false), + B_4096_1_coral("minecraft:coral", "", 4096, 1, "blocks/observer.png", 0xff3d6e86, false), + B_4097_2_coral("minecraft:coral", "", 4097, 2, "blocks/observer.png", 0xff3d6e86, false), + B_4098_3_coral("minecraft:coral", "", 4098, 3, "blocks/observer.png", 0xff3d6e86, false), + B_4099_4_coral("minecraft:coral", "", 4099, 4, "blocks/observer.png", 0xff3d6e86, false), + B_4100_5_coral("minecraft:coral", "", 4100, 5, "blocks/observer.png", 0xff3d6e86, false), + B_4101_6_coral("minecraft:coral", "", 4101, 6, "blocks/observer.png", 0xff3d6e86, false), + B_4102_7_coral("minecraft:coral", "", 4102, 7, "blocks/observer.png", 0xff3d6e86, false), + B_4103_8_coral("minecraft:coral", "", 4103, 8, "blocks/observer.png", 0xff3d6e86, false), + B_4104_9_coral("minecraft:coral", "", 4104, 9, "blocks/observer.png", 0xff3d6e86, false), + B_4105_10_coral("minecraft:coral", "", 4105, 10, "blocks/observer.png", 0xff3d6e86, false), + B_4106_11_coral("minecraft:coral", "", 4106, 11, "blocks/observer.png", 0xff3d6e86, false), + B_4107_12_coral("minecraft:coral", "", 4107, 12, "blocks/observer.png", 0xff3d6e86, false), + B_4108_13_coral("minecraft:coral", "", 4108, 13, "blocks/observer.png", 0xff3d6e86, false), + B_4109_14_coral("minecraft:coral", "", 4109, 14, "blocks/observer.png", 0xff3d6e86, false), + B_4110_15_coral("minecraft:coral", "", 4110, 15, "blocks/observer.png", 0xff3d6e86, false), + B_4111_0_coral_block("minecraft:coral_block", "", 4111, 0, "blocks/observer.png", 0xff3d6e86, false), + B_4112_1_coral_block("minecraft:coral_block", "", 4112, 1, "blocks/observer.png", 0xff3d6e86, false), + B_4113_2_coral_block("minecraft:coral_block", "", 4113, 2, "blocks/observer.png", 0xff3d6e86, false), + B_4114_3_coral_block("minecraft:coral_block", "", 4114, 3, "blocks/observer.png", 0xff3d6e86, false), + B_4115_4_coral_block("minecraft:coral_block", "", 4115, 4, "blocks/observer.png", 0xff3d6e86, false), + B_4116_5_coral_block("minecraft:coral_block", "", 4116, 5, "blocks/observer.png", 0xff3d6e86, false), + B_4117_6_coral_block("minecraft:coral_block", "", 4117, 6, "blocks/observer.png", 0xff3d6e86, false), + B_4118_7_coral_block("minecraft:coral_block", "", 4118, 7, "blocks/observer.png", 0xff3d6e86, false), + B_4119_8_coral_block("minecraft:coral_block", "", 4119, 8, "blocks/observer.png", 0xff3d6e86, false), + B_4120_9_coral_block("minecraft:coral_block", "", 4120, 9, "blocks/observer.png", 0xff3d6e86, false), + B_4121_10_coral_block("minecraft:coral_block", "", 4121, 10, "blocks/observer.png", 0xff3d6e86, false), + B_4122_11_coral_block("minecraft:coral_block", "", 4122, 11, "blocks/observer.png", 0xff3d6e86, false), + B_4123_12_coral_block("minecraft:coral_block", "", 4123, 12, "blocks/observer.png", 0xff3d6e86, false), + B_4124_13_coral_block("minecraft:coral_block", "", 4124, 13, "blocks/observer.png", 0xff3d6e86, false), + B_4125_14_coral_block("minecraft:coral_block", "", 4125, 14, "blocks/observer.png", 0xff3d6e86, false), + B_4126_15_coral_block("minecraft:coral_block", "", 4126, 15, "blocks/observer.png", 0xff3d6e86, false), + B_4127_0_coral_fan("minecraft:coral_fan", "", 4127, 0, "blocks/observer.png", 0xff3d6e86, false), + B_4128_1_coral_fan("minecraft:coral_fan", "", 4128, 1, "blocks/observer.png", 0xff3d6e86, false), + B_4129_2_coral_fan("minecraft:coral_fan", "", 4129, 2, "blocks/observer.png", 0xff3d6e86, false), + B_4130_3_coral_fan("minecraft:coral_fan", "", 4130, 3, "blocks/observer.png", 0xff3d6e86, false), + B_4131_4_coral_fan("minecraft:coral_fan", "", 4131, 4, "blocks/observer.png", 0xff3d6e86, false), + B_4132_5_coral_fan("minecraft:coral_fan", "", 4132, 5, "blocks/observer.png", 0xff3d6e86, false), + B_4133_6_coral_fan("minecraft:coral_fan", "", 4133, 6, "blocks/observer.png", 0xff3d6e86, false), + B_4134_7_coral_fan("minecraft:coral_fan", "", 4134, 7, "blocks/observer.png", 0xff3d6e86, false), + B_4135_8_coral_fan("minecraft:coral_fan", "", 4135, 8, "blocks/observer.png", 0xff3d6e86, false), + B_4136_9_coral_fan("minecraft:coral_fan", "", 4136, 9, "blocks/observer.png", 0xff3d6e86, false), + B_4137_10_coral_fan("minecraft:coral_fan", "", 4137, 10, "blocks/observer.png", 0xff3d6e86, false), + B_4138_11_coral_fan("minecraft:coral_fan", "", 4138, 11, "blocks/observer.png", 0xff3d6e86, false), + B_4139_12_coral_fan("minecraft:coral_fan", "", 4139, 12, "blocks/observer.png", 0xff3d6e86, false), + B_4140_13_coral_fan("minecraft:coral_fan", "", 4140, 13, "blocks/observer.png", 0xff3d6e86, false), + B_4141_14_coral_fan("minecraft:coral_fan", "", 4141, 14, "blocks/observer.png", 0xff3d6e86, false), + B_4142_15_coral_fan("minecraft:coral_fan", "", 4142, 15, "blocks/observer.png", 0xff3d6e86, false), + B_4143_0_coral_fan_dead("minecraft:coral_fan_dead", "", 4143, 0, "blocks/observer.png", 0xFFC8C8C8, false), + B_4144_1_coral_fan_dead("minecraft:coral_fan_dead", "", 4144, 1, "blocks/observer.png", 0xFFC8C8C8, false), + B_4145_2_coral_fan_dead("minecraft:coral_fan_dead", "", 4145, 2, "blocks/observer.png", 0xFFC8C8C8, false), + B_4146_3_coral_fan_dead("minecraft:coral_fan_dead", "", 4146, 3, "blocks/observer.png", 0xFFC8C8C8, false), + B_4147_4_coral_fan_dead("minecraft:coral_fan_dead", "", 4147, 4, "blocks/observer.png", 0xFFC8C8C8, false), + B_4148_5_coral_fan_dead("minecraft:coral_fan_dead", "", 4148, 5, "blocks/observer.png", 0xFFC8C8C8, false), + B_4149_6_coral_fan_dead("minecraft:coral_fan_dead", "", 4149, 6, "blocks/observer.png", 0xFFC8C8C8, false), + B_4150_7_coral_fan_dead("minecraft:coral_fan_dead", "", 4150, 7, "blocks/observer.png", 0xFFC8C8C8, false), + B_4151_8_coral_fan_dead("minecraft:coral_fan_dead", "", 4151, 8, "blocks/observer.png", 0xFFC8C8C8, false), + B_4152_9_coral_fan_dead("minecraft:coral_fan_dead", "", 4152, 9, "blocks/observer.png", 0xFFC8C8C8, false), + B_4153_10_coral_fan_dead("minecraft:coral_fan_dead", "", 4153, 10, "blocks/observer.png", 0xFFC8C8C8, false), + B_4154_11_coral_fan_dead("minecraft:coral_fan_dead", "", 4154, 11, "blocks/observer.png", 0xFFC8C8C8, false), + B_4155_12_coral_fan_dead("minecraft:coral_fan_dead", "", 4155, 12, "blocks/observer.png", 0xFFC8C8C8, false), + B_4156_13_coral_fan_dead("minecraft:coral_fan_dead", "", 4156, 13, "blocks/observer.png", 0xFFC8C8C8, false), + B_4157_14_coral_fan_dead("minecraft:coral_fan_dead", "", 4157, 14, "blocks/observer.png", 0xFFC8C8C8, false), + B_4158_15_coral_fan_dead("minecraft:coral_fan_dead", "", 4158, 15, "blocks/observer.png", 0xFFC8C8C8, false), + B_4159_0_coral_fan_hang("minecraft:coral_fan_hang", "", 4159, 0, "blocks/observer.png", 0xff3d6e86, false), + B_4160_1_coral_fan_hang("minecraft:coral_fan_hang", "", 4160, 1, "blocks/observer.png", 0xff3d6e86, false), + B_4161_2_coral_fan_hang("minecraft:coral_fan_hang", "", 4161, 2, "blocks/observer.png", 0xff3d6e86, false), + B_4162_3_coral_fan_hang("minecraft:coral_fan_hang", "", 4162, 3, "blocks/observer.png", 0xff3d6e86, false), + B_4163_4_coral_fan_hang("minecraft:coral_fan_hang", "", 4163, 4, "blocks/observer.png", 0xff3d6e86, false), + B_4164_5_coral_fan_hang("minecraft:coral_fan_hang", "", 4164, 5, "blocks/observer.png", 0xff3d6e86, false), + B_4165_6_coral_fan_hang("minecraft:coral_fan_hang", "", 4165, 6, "blocks/observer.png", 0xff3d6e86, false), + B_4166_7_coral_fan_hang("minecraft:coral_fan_hang", "", 4166, 7, "blocks/observer.png", 0xff3d6e86, false), + B_4167_8_coral_fan_hang("minecraft:coral_fan_hang", "", 4167, 8, "blocks/observer.png", 0xff3d6e86, false), + B_4168_9_coral_fan_hang("minecraft:coral_fan_hang", "", 4168, 9, "blocks/observer.png", 0xff3d6e86, false), + B_4169_10_coral_fan_hang("minecraft:coral_fan_hang", "", 4169, 10, "blocks/observer.png", 0xff3d6e86, false), + B_4170_11_coral_fan_hang("minecraft:coral_fan_hang", "", 4170, 11, "blocks/observer.png", 0xff3d6e86, false), + B_4171_12_coral_fan_hang("minecraft:coral_fan_hang", "", 4171, 12, "blocks/observer.png", 0xff3d6e86, false), + B_4172_13_coral_fan_hang("minecraft:coral_fan_hang", "", 4172, 13, "blocks/observer.png", 0xff3d6e86, false), + B_4173_14_coral_fan_hang("minecraft:coral_fan_hang", "", 4173, 14, "blocks/observer.png", 0xff3d6e86, false), + B_4174_15_coral_fan_hang("minecraft:coral_fan_hang", "", 4174, 15, "blocks/observer.png", 0xff3d6e86, false), + B_4175_0_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4175, 0, "blocks/observer.png", 0xff3d6e86, false), + B_4176_1_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4176, 1, "blocks/observer.png", 0xff3d6e86, false), + B_4177_2_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4177, 2, "blocks/observer.png", 0xff3d6e86, false), + B_4178_3_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4178, 3, "blocks/observer.png", 0xff3d6e86, false), + B_4179_4_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4179, 4, "blocks/observer.png", 0xff3d6e86, false), + B_4180_5_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4180, 5, "blocks/observer.png", 0xff3d6e86, false), + B_4181_6_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4181, 6, "blocks/observer.png", 0xff3d6e86, false), + B_4182_7_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4182, 7, "blocks/observer.png", 0xff3d6e86, false), + B_4183_8_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4183, 8, "blocks/observer.png", 0xff3d6e86, false), + B_4184_9_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4184, 9, "blocks/observer.png", 0xff3d6e86, false), + B_4185_10_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4185, 10, "blocks/observer.png", 0xff3d6e86, false), + B_4186_11_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4186, 11, "blocks/observer.png", 0xff3d6e86, false), + B_4187_12_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4187, 12, "blocks/observer.png", 0xff3d6e86, false), + B_4188_13_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4188, 13, "blocks/observer.png", 0xff3d6e86, false), + B_4189_14_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4189, 14, "blocks/observer.png", 0xff3d6e86, false), + B_4190_15_coral_fan_hang2("minecraft:coral_fan_hang2", "", 4190, 15, "blocks/observer.png", 0xff3d6e86, false), + B_4191_0_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4191, 0, "blocks/observer.png", 0xff3d6e86, false), + B_4192_1_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4192, 1, "blocks/observer.png", 0xff3d6e86, false), + B_4193_2_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4193, 2, "blocks/observer.png", 0xff3d6e86, false), + B_4194_3_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4194, 3, "blocks/observer.png", 0xff3d6e86, false), + B_4195_4_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4195, 4, "blocks/observer.png", 0xff3d6e86, false), + B_4196_5_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4196, 5, "blocks/observer.png", 0xff3d6e86, false), + B_4197_6_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4197, 6, "blocks/observer.png", 0xff3d6e86, false), + B_4198_7_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4198, 7, "blocks/observer.png", 0xff3d6e86, false), + B_4199_8_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4199, 8, "blocks/observer.png", 0xff3d6e86, false), + B_4200_9_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4200, 9, "blocks/observer.png", 0xff3d6e86, false), + B_4201_10_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4201, 10, "blocks/observer.png", 0xff3d6e86, false), + B_4202_11_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4202, 11, "blocks/observer.png", 0xff3d6e86, false), + B_4203_12_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4203, 12, "blocks/observer.png", 0xff3d6e86, false), + B_4204_13_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4204, 13, "blocks/observer.png", 0xff3d6e86, false), + B_4205_14_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4205, 14, "blocks/observer.png", 0xff3d6e86, false), + B_4206_15_coral_fan_hang3("minecraft:coral_fan_hang3", "", 4206, 15, "blocks/observer.png", 0xff3d6e86, false), + B_4207_0_kelp("minecraft:kelp", "", 4207, 0, "blocks/observer.png", 0xff04833e, false), + B_4208_1_kelp("minecraft:kelp", "", 4208, 1, "blocks/observer.png", 0xff04833e, false), + B_4209_2_kelp("minecraft:kelp", "", 4209, 2, "blocks/observer.png", 0xff04833e, false), + B_4210_3_kelp("minecraft:kelp", "", 4210, 3, "blocks/observer.png", 0xff04833e, false), + B_4211_4_kelp("minecraft:kelp", "", 4211, 4, "blocks/observer.png", 0xff04833e, false), + B_4212_5_kelp("minecraft:kelp", "", 4212, 5, "blocks/observer.png", 0xff04833e, false), + B_4213_6_kelp("minecraft:kelp", "", 4213, 6, "blocks/observer.png", 0xff04833e, false), + B_4214_7_kelp("minecraft:kelp", "", 4214, 7, "blocks/observer.png", 0xff04833e, false), + B_4215_8_kelp("minecraft:kelp", "", 4215, 8, "blocks/observer.png", 0xff04833e, false), + B_4216_9_kelp("minecraft:kelp", "", 4216, 9, "blocks/observer.png", 0xff04833e, false), + B_4217_10_kelp("minecraft:kelp", "", 4217, 10, "blocks/observer.png", 0xff04833e, false), + B_4218_11_kelp("minecraft:kelp", "", 4218, 11, "blocks/observer.png", 0xff04833e, false), + B_4219_12_kelp("minecraft:kelp", "", 4219, 12, "blocks/observer.png", 0xff04833e, false), + B_4220_13_kelp("minecraft:kelp", "", 4220, 13, "blocks/observer.png", 0xff04833e, false), + B_4221_14_kelp("minecraft:kelp", "", 4221, 14, "blocks/observer.png", 0xff04833e, false), + B_4222_15_kelp("minecraft:kelp", "", 4222, 15, "blocks/observer.png", 0xff04833e, false), + B_4223_0_dried_kelp_block("minecraft:dried_kelp_block", "", 4223, 0, "blocks/observer.png", 0xff044b4b, false), + B_4224_0_acacia_button("minecraft:acacia_button", "", 4224, 0, "blocks/observer.png", 0x5f934f39, false), + B_4225_1_acacia_button("minecraft:acacia_button", "", 4225, 1, "blocks/observer.png", 0x5f934f39, false), + B_4226_2_acacia_button("minecraft:acacia_button", "", 4226, 2, "blocks/observer.png", 0x5f934f39, false), + B_4227_3_acacia_button("minecraft:acacia_button", "", 4227, 3, "blocks/observer.png", 0x5f934f39, false), + B_4228_4_acacia_button("minecraft:acacia_button", "", 4228, 4, "blocks/observer.png", 0x5f934f39, false), + B_4229_5_acacia_button("minecraft:acacia_button", "", 4229, 5, "blocks/observer.png", 0x5f934f39, false), + B_4230_6_acacia_button("minecraft:acacia_button", "", 4230, 6, "blocks/observer.png", 0x5f934f39, false), + B_4231_7_acacia_button("minecraft:acacia_button", "", 4231, 7, "blocks/observer.png", 0x5f934f39, false), + B_4232_8_acacia_button("minecraft:acacia_button", "", 4232, 8, "blocks/observer.png", 0x5f934f39, false), + B_4233_9_acacia_button("minecraft:acacia_button", "", 4233, 9, "blocks/observer.png", 0x5f934f39, false), + B_4234_10_acacia_button("minecraft:acacia_button", "", 4234, 10, "blocks/observer.png", 0x5f934f39, false), + B_4235_11_acacia_button("minecraft:acacia_button", "", 4235, 11, "blocks/observer.png", 0x5f934f39, false), + B_4236_12_acacia_button("minecraft:acacia_button", "", 4236, 12, "blocks/observer.png", 0x5f934f39, false), + B_4237_13_acacia_button("minecraft:acacia_button", "", 4237, 13, "blocks/observer.png", 0x5f934f39, false), + B_4238_14_acacia_button("minecraft:acacia_button", "", 4238, 14, "blocks/observer.png", 0x5f934f39, false), + B_4239_15_acacia_button("minecraft:acacia_button", "", 4239, 15, "blocks/observer.png", 0x5f934f39, false), + B_4240_0_birch_button("minecraft:birch_button", "", 4240, 0, "blocks/observer.png", 0xffdabd8d, false), + B_4241_1_birch_button("minecraft:birch_button", "", 4241, 1, "blocks/observer.png", 0xffdabd8d, false), + B_4242_2_birch_button("minecraft:birch_button", "", 4242, 2, "blocks/observer.png", 0xffdabd8d, false), + B_4243_3_birch_button("minecraft:birch_button", "", 4243, 3, "blocks/observer.png", 0xffdabd8d, false), + B_4244_4_birch_button("minecraft:birch_button", "", 4244, 4, "blocks/observer.png", 0xffdabd8d, false), + B_4245_5_birch_button("minecraft:birch_button", "", 4245, 5, "blocks/observer.png", 0xffdabd8d, false), + B_4246_6_birch_button("minecraft:birch_button", "", 4246, 6, "blocks/observer.png", 0xffdabd8d, false), + B_4247_7_birch_button("minecraft:birch_button", "", 4247, 7, "blocks/observer.png", 0xffdabd8d, false), + B_4248_8_birch_button("minecraft:birch_button", "", 4248, 8, "blocks/observer.png", 0xffdabd8d, false), + B_4249_9_birch_button("minecraft:birch_button", "", 4249, 9, "blocks/observer.png", 0xffdabd8d, false), + B_4250_10_birch_button("minecraft:birch_button", "", 4250, 10, "blocks/observer.png", 0xffdabd8d, false), + B_4251_11_birch_button("minecraft:birch_button", "", 4251, 11, "blocks/observer.png", 0xffdabd8d, false), + B_4252_12_birch_button("minecraft:birch_button", "", 4252, 12, "blocks/observer.png", 0xffdabd8d, false), + B_4253_13_birch_button("minecraft:birch_button", "", 4253, 13, "blocks/observer.png", 0xffdabd8d, false), + B_4254_14_birch_button("minecraft:birch_button", "", 4254, 14, "blocks/observer.png", 0xffdabd8d, false), + B_4255_15_birch_button("minecraft:birch_button", "", 4255, 15, "blocks/observer.png", 0xffdabd8d, false), + B_4256_0_dark_oak_button("minecraft:dark_oak_button", "", 4256, 0, "blocks/observer.png", 0xff2d2213, false), + B_4257_1_dark_oak_button("minecraft:dark_oak_button", "", 4257, 1, "blocks/observer.png", 0xff2d2213, false), + B_4258_2_dark_oak_button("minecraft:dark_oak_button", "", 4258, 2, "blocks/observer.png", 0xff2d2213, false), + B_4259_3_dark_oak_button("minecraft:dark_oak_button", "", 4259, 3, "blocks/observer.png", 0xff2d2213, false), + B_4260_4_dark_oak_button("minecraft:dark_oak_button", "", 4260, 4, "blocks/observer.png", 0xff2d2213, false), + B_4261_5_dark_oak_button("minecraft:dark_oak_button", "", 4261, 5, "blocks/observer.png", 0xff2d2213, false), + B_4262_6_dark_oak_button("minecraft:dark_oak_button", "", 4262, 6, "blocks/observer.png", 0xff2d2213, false), + B_4263_7_dark_oak_button("minecraft:dark_oak_button", "", 4263, 7, "blocks/observer.png", 0xff2d2213, false), + B_4264_8_dark_oak_button("minecraft:dark_oak_button", "", 4264, 8, "blocks/observer.png", 0xff2d2213, false), + B_4265_9_dark_oak_button("minecraft:dark_oak_button", "", 4265, 9, "blocks/observer.png", 0xff2d2213, false), + B_4266_10_dark_oak_button("minecraft:dark_oak_button", "", 4266, 10, "blocks/observer.png", 0xff2d2213, false), + B_4267_11_dark_oak_button("minecraft:dark_oak_button", "", 4267, 11, "blocks/observer.png", 0xff2d2213, false), + B_4268_12_dark_oak_button("minecraft:dark_oak_button", "", 4268, 12, "blocks/observer.png", 0xff2d2213, false), + B_4269_13_dark_oak_button("minecraft:dark_oak_button", "", 4269, 13, "blocks/observer.png", 0xff2d2213, false), + B_4270_14_dark_oak_button("minecraft:dark_oak_button", "", 4270, 14, "blocks/observer.png", 0xff2d2213, false), + B_4271_15_dark_oak_button("minecraft:dark_oak_button", "", 4271, 15, "blocks/observer.png", 0xff2d2213, false), + B_4272_0_jungle_button("minecraft:jungle_button", "", 4272, 0, "blocks/observer.png", 0xffBa7d5d, false), + B_4273_1_jungle_button("minecraft:jungle_button", "", 4273, 1, "blocks/observer.png", 0xffBa7d5d, false), + B_4274_2_jungle_button("minecraft:jungle_button", "", 4274, 2, "blocks/observer.png", 0xffBa7d5d, false), + B_4275_3_jungle_button("minecraft:jungle_button", "", 4275, 3, "blocks/observer.png", 0xffBa7d5d, false), + B_4276_4_jungle_button("minecraft:jungle_button", "", 4276, 4, "blocks/observer.png", 0xffBa7d5d, false), + B_4277_5_jungle_button("minecraft:jungle_button", "", 4277, 5, "blocks/observer.png", 0xffBa7d5d, false), + B_4278_6_jungle_button("minecraft:jungle_button", "", 4278, 6, "blocks/observer.png", 0xffBa7d5d, false), + B_4279_7_jungle_button("minecraft:jungle_button", "", 4279, 7, "blocks/observer.png", 0xffBa7d5d, false), + B_4280_8_jungle_button("minecraft:jungle_button", "", 4280, 8, "blocks/observer.png", 0xffBa7d5d, false), + B_4281_9_jungle_button("minecraft:jungle_button", "", 4281, 9, "blocks/observer.png", 0xffBa7d5d, false), + B_4282_10_jungle_button("minecraft:jungle_button", "", 4282, 10, "blocks/observer.png", 0xffBa7d5d, false), + B_4283_11_jungle_button("minecraft:jungle_button", "", 4283, 11, "blocks/observer.png", 0xffBa7d5d, false), + B_4284_12_jungle_button("minecraft:jungle_button", "", 4284, 12, "blocks/observer.png", 0xffBa7d5d, false), + B_4285_13_jungle_button("minecraft:jungle_button", "", 4285, 13, "blocks/observer.png", 0xffBa7d5d, false), + B_4286_14_jungle_button("minecraft:jungle_button", "", 4286, 14, "blocks/observer.png", 0xffBa7d5d, false), + B_4287_15_jungle_button("minecraft:jungle_button", "", 4287, 15, "blocks/observer.png", 0xffBa7d5d, false), + B_4288_0_spruce_button("minecraft:spruce_button", "", 4288, 0, "blocks/observer.png", 0xff5a3d0d, false), + B_4289_1_spruce_button("minecraft:spruce_button", "", 4289, 1, "blocks/observer.png", 0xff5a3d0d, false), + B_4290_2_spruce_button("minecraft:spruce_button", "", 4290, 2, "blocks/observer.png", 0xff5a3d0d, false), + B_4291_3_spruce_button("minecraft:spruce_button", "", 4291, 3, "blocks/observer.png", 0xff5a3d0d, false), + B_4292_4_spruce_button("minecraft:spruce_button", "", 4292, 4, "blocks/observer.png", 0xff5a3d0d, false), + B_4293_5_spruce_button("minecraft:spruce_button", "", 4293, 5, "blocks/observer.png", 0xff5a3d0d, false), + B_4294_6_spruce_button("minecraft:spruce_button", "", 4294, 6, "blocks/observer.png", 0xff5a3d0d, false), + B_4295_7_spruce_button("minecraft:spruce_button", "", 4295, 7, "blocks/observer.png", 0xff5a3d0d, false), + B_4296_8_spruce_button("minecraft:spruce_button", "", 4296, 8, "blocks/observer.png", 0xff5a3d0d, false), + B_4297_9_spruce_button("minecraft:spruce_button", "", 4297, 9, "blocks/observer.png", 0xff5a3d0d, false), + B_4298_10_spruce_button("minecraft:spruce_button", "", 4298, 10, "blocks/observer.png", 0xff5a3d0d, false), + B_4299_11_spruce_button("minecraft:spruce_button", "", 4299, 11, "blocks/observer.png", 0xff5a3d0d, false), + B_4300_12_spruce_button("minecraft:spruce_button", "", 4300, 12, "blocks/observer.png", 0xff5a3d0d, false), + B_4301_13_spruce_button("minecraft:spruce_button", "", 4301, 13, "blocks/observer.png", 0xff5a3d0d, false), + B_4302_14_spruce_button("minecraft:spruce_button", "", 4302, 14, "blocks/observer.png", 0xff5a3d0d, false), + B_4303_15_spruce_button("minecraft:spruce_button", "", 4303, 15, "blocks/observer.png", 0xff5a3d0d, false), + B_4304_0_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4304, 0, "blocks/observer.png", 0xff934f39, false), + B_4305_1_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4305, 1, "blocks/observer.png", 0xff934f39, false), + B_4306_2_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4306, 2, "blocks/observer.png", 0xff934f39, false), + B_4307_3_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4307, 3, "blocks/observer.png", 0xff934f39, false), + B_4308_4_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4308, 4, "blocks/observer.png", 0xff934f39, false), + B_4309_5_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4309, 5, "blocks/observer.png", 0xff934f39, false), + B_4310_6_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4310, 6, "blocks/observer.png", 0xff934f39, false), + B_4311_7_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4311, 7, "blocks/observer.png", 0xff934f39, false), + B_4312_8_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4312, 8, "blocks/observer.png", 0xff934f39, false), + B_4313_9_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4313, 9, "blocks/observer.png", 0xff934f39, false), + B_4314_10_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4314, 10, "blocks/observer.png", 0xff934f39, false), + B_4315_11_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4315, 11, "blocks/observer.png", 0xff934f39, false), + B_4316_12_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4316, 12, "blocks/observer.png", 0xff934f39, false), + B_4317_13_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4317, 13, "blocks/observer.png", 0xff934f39, false), + B_4318_14_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4318, 14, "blocks/observer.png", 0xff934f39, false), + B_4319_15_acacia_trapdoor("minecraft:acacia_trapdoor", "", 4319, 15, "blocks/observer.png", 0xff934f39, false), + B_4320_0_birch_trapdoor("minecraft:birch_trapdoor", "", 4320, 0, "blocks/observer.png", 0xffdabd8d, false), + B_4321_1_birch_trapdoor("minecraft:birch_trapdoor", "", 4321, 1, "blocks/observer.png", 0xffdabd8d, false), + B_4322_2_birch_trapdoor("minecraft:birch_trapdoor", "", 4322, 2, "blocks/observer.png", 0xffdabd8d, false), + B_4323_3_birch_trapdoor("minecraft:birch_trapdoor", "", 4323, 3, "blocks/observer.png", 0xffdabd8d, false), + B_4324_4_birch_trapdoor("minecraft:birch_trapdoor", "", 4324, 4, "blocks/observer.png", 0xffdabd8d, false), + B_4325_5_birch_trapdoor("minecraft:birch_trapdoor", "", 4325, 5, "blocks/observer.png", 0xffdabd8d, false), + B_4326_6_birch_trapdoor("minecraft:birch_trapdoor", "", 4326, 6, "blocks/observer.png", 0xffdabd8d, false), + B_4327_7_birch_trapdoor("minecraft:birch_trapdoor", "", 4327, 7, "blocks/observer.png", 0xffdabd8d, false), + B_4328_8_birch_trapdoor("minecraft:birch_trapdoor", "", 4328, 8, "blocks/observer.png", 0xffdabd8d, false), + B_4329_9_birch_trapdoor("minecraft:birch_trapdoor", "", 4329, 9, "blocks/observer.png", 0xffdabd8d, false), + B_4330_10_birch_trapdoor("minecraft:birch_trapdoor", "", 4330, 10, "blocks/observer.png", 0xffdabd8d, false), + B_4331_11_birch_trapdoor("minecraft:birch_trapdoor", "", 4331, 11, "blocks/observer.png", 0xffdabd8d, false), + B_4332_12_birch_trapdoor("minecraft:birch_trapdoor", "", 4332, 12, "blocks/observer.png", 0xffdabd8d, false), + B_4333_13_birch_trapdoor("minecraft:birch_trapdoor", "", 4333, 13, "blocks/observer.png", 0xffdabd8d, false), + B_4334_14_birch_trapdoor("minecraft:birch_trapdoor", "", 4334, 14, "blocks/observer.png", 0xffdabd8d, false), + B_4335_15_birch_trapdoor("minecraft:birch_trapdoor", "", 4335, 15, "blocks/observer.png", 0xffdabd8d, false), + B_4336_0_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4336, 0, "blocks/observer.png", 0xff2d2213, false), + B_4337_1_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4337, 1, "blocks/observer.png", 0xff2d2213, false), + B_4338_2_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4338, 2, "blocks/observer.png", 0xff2d2213, false), + B_4339_3_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4339, 3, "blocks/observer.png", 0xff2d2213, false), + B_4340_4_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4340, 4, "blocks/observer.png", 0xff2d2213, false), + B_4341_5_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4341, 5, "blocks/observer.png", 0xff2d2213, false), + B_4342_6_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4342, 6, "blocks/observer.png", 0xff2d2213, false), + B_4343_7_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4343, 7, "blocks/observer.png", 0xff2d2213, false), + B_4344_8_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4344, 8, "blocks/observer.png", 0xff2d2213, false), + B_4345_9_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4345, 9, "blocks/observer.png", 0xff2d2213, false), + B_4346_10_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4346, 10, "blocks/observer.png", 0xff2d2213, false), + B_4347_11_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4347, 11, "blocks/observer.png", 0xff2d2213, false), + B_4348_12_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4348, 12, "blocks/observer.png", 0xff2d2213, false), + B_4349_13_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4349, 13, "blocks/observer.png", 0xff2d2213, false), + B_4350_14_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4350, 14, "blocks/observer.png", 0xff2d2213, false), + B_4351_15_dark_oak_trapdoor("minecraft:dark_oak_trapdoor", "", 4351, 15, "blocks/observer.png", 0xff2d2213, false), + B_4352_0_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4352, 0, "blocks/observer.png", 0xffBa7d5d, false), + B_4353_1_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4353, 1, "blocks/observer.png", 0xffBa7d5d, false), + B_4354_2_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4354, 2, "blocks/observer.png", 0xffBa7d5d, false), + B_4355_3_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4355, 3, "blocks/observer.png", 0xffBa7d5d, false), + B_4356_4_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4356, 4, "blocks/observer.png", 0xffBa7d5d, false), + B_4357_5_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4357, 5, "blocks/observer.png", 0xffBa7d5d, false), + B_4358_6_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4358, 6, "blocks/observer.png", 0xffBa7d5d, false), + B_4359_7_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4359, 7, "blocks/observer.png", 0xffBa7d5d, false), + B_4360_8_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4360, 8, "blocks/observer.png", 0xffBa7d5d, false), + B_4361_9_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4361, 9, "blocks/observer.png", 0xffBa7d5d, false), + B_4362_10_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4362, 10, "blocks/observer.png", 0xffBa7d5d, false), + B_4363_11_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4363, 11, "blocks/observer.png", 0xffBa7d5d, false), + B_4364_12_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4364, 12, "blocks/observer.png", 0xffBa7d5d, false), + B_4365_13_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4365, 13, "blocks/observer.png", 0xffBa7d5d, false), + B_4366_14_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4366, 14, "blocks/observer.png", 0xffBa7d5d, false), + B_4367_15_jungle_trapdoor("minecraft:jungle_trapdoor", "", 4367, 15, "blocks/observer.png", 0xffBa7d5d, false), + B_4368_0_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4368, 0, "blocks/observer.png", 0xff5a3d0d, false), + B_4369_1_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4369, 1, "blocks/observer.png", 0xff5a3d0d, false), + B_4370_2_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4370, 2, "blocks/observer.png", 0xff5a3d0d, false), + B_4371_3_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4371, 3, "blocks/observer.png", 0xff5a3d0d, false), + B_4372_4_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4372, 4, "blocks/observer.png", 0xff5a3d0d, false), + B_4373_5_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4373, 5, "blocks/observer.png", 0xff5a3d0d, false), + B_4374_6_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4374, 6, "blocks/observer.png", 0xff5a3d0d, false), + B_4375_7_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4375, 7, "blocks/observer.png", 0xff5a3d0d, false), + B_4376_8_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4376, 8, "blocks/observer.png", 0xff5a3d0d, false), + B_4377_9_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4377, 9, "blocks/observer.png", 0xff5a3d0d, false), + B_4378_10_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4378, 10, "blocks/observer.png", 0xff5a3d0d, false), + B_4379_11_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4379, 11, "blocks/observer.png", 0xff5a3d0d, false), + B_4380_12_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4380, 12, "blocks/observer.png", 0xff5a3d0d, false), + B_4381_13_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4381, 13, "blocks/observer.png", 0xff5a3d0d, false), + B_4382_14_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4382, 14, "blocks/observer.png", 0xff5a3d0d, false), + B_4383_15_spruce_trapdoor("minecraft:spruce_trapdoor", "", 4383, 15, "blocks/observer.png", 0xff5a3d0d, false), + B_4384_0_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4384, 0, "blocks/observer.png", 0xff934f39, false), + B_4385_1_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4385, 1, "blocks/observer.png", 0xff934f39, false), + B_4386_2_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4386, 2, "blocks/observer.png", 0xff934f39, false), + B_4387_3_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4387, 3, "blocks/observer.png", 0xff934f39, false), + B_4388_4_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4388, 4, "blocks/observer.png", 0xff934f39, false), + B_4389_5_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4389, 5, "blocks/observer.png", 0xff934f39, false), + B_4390_6_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4390, 6, "blocks/observer.png", 0xff934f39, false), + B_4391_7_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4391, 7, "blocks/observer.png", 0xff934f39, false), + B_4392_8_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4392, 8, "blocks/observer.png", 0xff934f39, false), + B_4393_9_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4393, 9, "blocks/observer.png", 0xff934f39, false), + B_4394_10_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4394, 10, "blocks/observer.png", 0xff934f39, false), + B_4395_11_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4395, 11, "blocks/observer.png", 0xff934f39, false), + B_4396_12_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4396, 12, "blocks/observer.png", 0xff934f39, false), + B_4397_13_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4397, 13, "blocks/observer.png", 0xff934f39, false), + B_4398_14_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4398, 14, "blocks/observer.png", 0xff934f39, false), + B_4399_15_acacia_pressure_plate("minecraft:acacia_pressure_plate", "", 4399, 15, "blocks/observer.png", 0xff934f39, false), + B_4400_0_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4400, 0, "blocks/observer.png", 0xffdabd8d, false), + B_4401_1_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4401, 1, "blocks/observer.png", 0xffdabd8d, false), + B_4402_2_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4402, 2, "blocks/observer.png", 0xffdabd8d, false), + B_4403_3_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4403, 3, "blocks/observer.png", 0xffdabd8d, false), + B_4404_4_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4404, 4, "blocks/observer.png", 0xffdabd8d, false), + B_4405_5_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4405, 5, "blocks/observer.png", 0xffdabd8d, false), + B_4406_6_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4406, 6, "blocks/observer.png", 0xffdabd8d, false), + B_4407_7_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4407, 7, "blocks/observer.png", 0xffdabd8d, false), + B_4408_8_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4408, 8, "blocks/observer.png", 0xffdabd8d, false), + B_4409_9_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4409, 9, "blocks/observer.png", 0xffdabd8d, false), + B_4410_10_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4410, 10, "blocks/observer.png", 0xffdabd8d, false), + B_4411_11_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4411, 11, "blocks/observer.png", 0xffdabd8d, false), + B_4412_12_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4412, 12, "blocks/observer.png", 0xffdabd8d, false), + B_4413_13_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4413, 13, "blocks/observer.png", 0xffdabd8d, false), + B_4414_14_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4414, 14, "blocks/observer.png", 0xffdabd8d, false), + B_4415_15_birch_pressure_plate("minecraft:birch_pressure_plate", "", 4415, 15, "blocks/observer.png", 0xffdabd8d, false), + B_4416_0_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4416, 0, "blocks/observer.png", 0xff2d2213, false), + B_4417_1_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4417, 1, "blocks/observer.png", 0xff2d2213, false), + B_4418_2_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4418, 2, "blocks/observer.png", 0xff2d2213, false), + B_4419_3_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4419, 3, "blocks/observer.png", 0xff2d2213, false), + B_4420_4_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4420, 4, "blocks/observer.png", 0xff2d2213, false), + B_4421_5_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4421, 5, "blocks/observer.png", 0xff2d2213, false), + B_4422_6_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4422, 6, "blocks/observer.png", 0xff2d2213, false), + B_4423_7_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4423, 7, "blocks/observer.png", 0xff2d2213, false), + B_4424_8_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4424, 8, "blocks/observer.png", 0xff2d2213, false), + B_4425_9_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4425, 9, "blocks/observer.png", 0xff2d2213, false), + B_4426_10_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4426, 10, "blocks/observer.png", 0xff2d2213, false), + B_4427_11_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4427, 11, "blocks/observer.png", 0xff2d2213, false), + B_4428_12_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4428, 12, "blocks/observer.png", 0xff2d2213, false), + B_4429_13_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4429, 13, "blocks/observer.png", 0xff2d2213, false), + B_4430_14_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4430, 14, "blocks/observer.png", 0xff2d2213, false), + B_4431_15_dark_oak_pressure_plate("minecraft:dark_oak_pressure_plate", "", 4431, 15, "blocks/observer.png", 0xff2d2213, false), + B_4432_0_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4432, 0, "blocks/observer.png", 0xffBa7d5d, false), + B_4433_1_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4433, 1, "blocks/observer.png", 0xffBa7d5d, false), + B_4434_2_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4434, 2, "blocks/observer.png", 0xffBa7d5d, false), + B_4435_3_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4435, 3, "blocks/observer.png", 0xffBa7d5d, false), + B_4436_4_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4436, 4, "blocks/observer.png", 0xffBa7d5d, false), + B_4437_5_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4437, 5, "blocks/observer.png", 0xffBa7d5d, false), + B_4438_6_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4438, 6, "blocks/observer.png", 0xffBa7d5d, false), + B_4439_7_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4439, 7, "blocks/observer.png", 0xffBa7d5d, false), + B_4440_8_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4440, 8, "blocks/observer.png", 0xffBa7d5d, false), + B_4441_9_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4441, 9, "blocks/observer.png", 0xffBa7d5d, false), + B_4442_10_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4442, 10, "blocks/observer.png", 0xffBa7d5d, false), + B_4443_11_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4443, 11, "blocks/observer.png", 0xffBa7d5d, false), + B_4444_12_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4444, 12, "blocks/observer.png", 0xffBa7d5d, false), + B_4445_13_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4445, 13, "blocks/observer.png", 0xffBa7d5d, false), + B_4446_14_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4446, 14, "blocks/observer.png", 0xffBa7d5d, false), + B_4447_15_jungle_pressure_plate("minecraft:jungle_pressure_plate", "", 4447, 15, "blocks/observer.png", 0xffBa7d5d, false), + B_4448_0_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4448, 0, "blocks/observer.png", 0xff5a3d0d, false), + B_4449_1_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4449, 1, "blocks/observer.png", 0xff5a3d0d, false), + B_4450_2_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4450, 2, "blocks/observer.png", 0xff5a3d0d, false), + B_4451_3_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4451, 3, "blocks/observer.png", 0xff5a3d0d, false), + B_4452_4_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4452, 4, "blocks/observer.png", 0xff5a3d0d, false), + B_4453_5_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4453, 5, "blocks/observer.png", 0xff5a3d0d, false), + B_4454_6_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4454, 6, "blocks/observer.png", 0xff5a3d0d, false), + B_4455_7_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4455, 7, "blocks/observer.png", 0xff5a3d0d, false), + B_4456_8_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4456, 8, "blocks/observer.png", 0xff5a3d0d, false), + B_4457_9_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4457, 9, "blocks/observer.png", 0xff5a3d0d, false), + B_4458_10_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4458, 10, "blocks/observer.png", 0xff5a3d0d, false), + B_4459_11_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4459, 11, "blocks/observer.png", 0xff5a3d0d, false), + B_4460_12_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4460, 12, "blocks/observer.png", 0xff5a3d0d, false), + B_4461_13_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4461, 13, "blocks/observer.png", 0xff5a3d0d, false), + B_4462_14_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4462, 14, "blocks/observer.png", 0xff5a3d0d, false), + B_4463_15_spruce_pressure_plate("minecraft:spruce_pressure_plate", "", 4463, 15, "blocks/observer.png", 0xff5a3d0d, false), + B_4464_0_carved_pumpkin("minecraft:carved_pumpkin", "", 4464, 0, "blocks/observer.png", 0xffc07615, false), + B_4465_1_carved_pumpkin("minecraft:carved_pumpkin", "", 4465, 1, "blocks/observer.png", 0xffc07615, false), + B_4466_2_carved_pumpkin("minecraft:carved_pumpkin", "", 4466, 2, "blocks/observer.png", 0xffc07615, false), + B_4467_3_carved_pumpkin("minecraft:carved_pumpkin", "", 4467, 3, "blocks/observer.png", 0xffc07615, false), + B_4468_0_sea_pickle("minecraft:sea_pickle", "", 4468, 0, "blocks/observer.png", 0xff10C38e, false), + B_4469_1_sea_pickle("minecraft:sea_pickle", "", 4469, 1, "blocks/observer.png", 0xff10C38e, false), + B_4470_2_sea_pickle("minecraft:sea_pickle", "", 4470, 2, "blocks/observer.png", 0xff10C38e, false), + B_4471_3_sea_pickle("minecraft:sea_pickle", "", 4471, 3, "blocks/observer.png", 0xff10C38e, false), + B_4472_4_sea_pickle("minecraft:sea_pickle", "", 4472, 4, "blocks/observer.png", 0xff10C38e, false), + B_4473_5_sea_pickle("minecraft:sea_pickle", "", 4473, 5, "blocks/observer.png", 0xff10C38e, false), + B_4474_6_sea_pickle("minecraft:sea_pickle", "", 4474, 6, "blocks/observer.png", 0xff10C38e, false), + B_4475_7_sea_pickle("minecraft:sea_pickle", "", 4475, 7, "blocks/observer.png", 0xff10C38e, false); + + private static final Map byDataName = new HashMap<>(); + private static final SparseArray blockMap; + private static final Map nameService; + private static final Map resolver; + + static { + blockMap = new SparseArray<>(); + nameService = new HashMap<>(256); + resolver = new HashMap<>(256); + KnownBlockRepr[] subMap; + KnownBlockRepr[] subMap2; + for (KnownBlockRepr b : KnownBlockRepr.values()) { + subMap = blockMap.get(b.id); + if (subMap == null) { + subMap = new KnownBlockRepr[16]; + blockMap.put(b.id, subMap); + } + subMap[b.subId] = b; + if (b.subId == 0) byDataName.put(b.identifier, b); + byDataName.put(b.identifier + "@" + b.subName, b); + nameService.put(b.identifier, b.id); + subMap2 = resolver.get(b.identifier); + if (subMap2 == null) { + subMap2 = new KnownBlockRepr[16]; + resolver.put(b.identifier, subMap2); + } + subMap2[b.subId] = b; + } + } + + public final int id, subId; + public final String identifier, subName; + public final String texPath; + public final int color; + public final boolean hasBiomeShading; + public Bitmap bitmap; + + KnownBlockRepr(String identifier, String subName, int id, int subId, String texPath, int color, boolean hasBiomeShading) { + this.id = id; + this.subId = subId; + this.identifier = identifier; + this.subName = subName; + this.texPath = texPath; + this.color = color; + this.hasBiomeShading = hasBiomeShading; + } + + public static KnownBlockRepr getByDataName(String dataName) { + return byDataName.get(dataName); + } + + public static void loadBitmaps(AssetManager assetManager) throws IOException { + if (Math.random() < 1) return; + for (KnownBlockRepr b : KnownBlockRepr.values()) { + if (b.bitmap == null && b.texPath != null) { + try { + b.bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(assetManager.open(b.texPath)), 32, 32, false); + } catch (FileNotFoundException e) { + //TODO file-paths were generated from block names; some do not actually exist... + //Log.w("File not found! "+b.texPath); + } catch (Exception e) { + Log.d(KnownBlockRepr.class, e); + } + } + } + } + + @NonNull + public static KnownBlockRepr getBestBlock(int id, int meta) { + KnownBlockRepr ret = getBlock(id, meta); + if (ret != null) return ret; + if (id >= 0) { + KnownBlockRepr[] subMap = blockMap.get(id); + if (subMap != null) { + ret = subMap[meta]; + if (ret == null) { + for (int i = 0; i < 16; i++) + if (subMap[i] != null) return subMap[i]; + } + } + } + return (ret == null) ? KnownBlockRepr.B_0_0_AIR : ret; + } + + @Nullable + public static KnownBlockRepr getBlock(int id, int meta) { + if (id < 0) return null; + KnownBlockRepr[] subMap = blockMap.get(id); + if (subMap == null) return null; + else return subMap[meta]; + } + + public static KnownBlockRepr getBlock(int runtimeId) { + int id = runtimeId >>> 8; + int data = runtimeId & 0xf; + return getBlock(id, data); + } + + public static int resolve(@NonNull String identifier) { + Integer i = nameService.get(identifier); + if (i == null) return 0; + return i; + } + + @Nullable + public static KnownBlockRepr getBlockNew(@NonNull String identifier, int val) { + KnownBlockRepr[] subMap = resolver.get(identifier); + if (subMap == null) return null; + if (val >= 0 && val <= 15) return subMap[val]; + return null; + } + + @NonNull + public static KnownBlockRepr guessBlockNew(@NonNull String identifier) { + KnownBlockRepr[] subMap = resolver.get(identifier); + if (subMap == null) return B_0_0_AIR; + for (int i = 0; i <= 15; i++) + if (subMap[i] != null) return subMap[i]; + return B_0_0_AIR; + } + + + public int getRuntimeId() { + return (id << 8) | subId; + } + + + public String getIdentifier() { + return identifier; + } + + + public int getVal() { + return subId; + } + + @Override + public Bitmap getBitmap() { + return this.bitmap; + } + + @NonNull + @Override + public NamedBitmapProvider getNamedBitmapProvider() { + return this; + } + + @NonNull + @Override + public String getBitmapDisplayName() { + return "ww123ww"; + } + + @NonNull + @Override + public String getBitmapDataName() { + return identifier + "@" + subName; + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/ListingBlock.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/ListingBlock.java new file mode 100644 index 00000000..c35fed9c --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/ListingBlock.java @@ -0,0 +1,559 @@ +package com.mithrilmania.blocktopograph.block; + +import android.content.res.AssetManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; + +import java.io.Serializable; +import java.lang.ref.WeakReference; + +public enum ListingBlock implements Serializable { + B_0_AIR("minecraft:air", 0, "Air", -1, 0, -1, 0, 0), + B_1_STONE("minecraft:stone", 1, "Stone", 0, 0, 98, 98, 98), + B_2_GRASS("minecraft:grass", 2, "Grass Block", 120, 0, 84, 86, 52), + B_3_DIRT("minecraft:dirt", 3, "Dirt", 240, 0, 105, 75, 52), + B_4_COBBLESTONE("minecraft:cobblestone", 4, "Cobblestone", 360, 0, 100, 99, 100), + B_5_PLANKS("minecraft:planks", 5, "Wood Planks", 480, 0, 126, 102, 61), + B_6_SAPLING("minecraft:sapling", 6, "Sapling", 600, 0, 75, 110, 41), + B_7_BEDROCK("minecraft:bedrock", 7, "Bedrock", 720, 0, 66, 66, 66), + B_8_FLOWING_WATER("minecraft:flowing_water", 8, "Water", 840, 0, 33, 62, 120), + B_9_WATER("minecraft:water", 9, "Stationary Water", 960, 0, 33, 62, 120), + B_10_FLOWING_LAVA("minecraft:flowing_lava", 10, "Lava", 1080, 0, 177, 84, 23), + B_11_LAVA("minecraft:lava", 11, "Stationary Lava", 1200, 0, 177, 84, 23), + B_12_SAND("minecraft:sand", 12, "Sand", 1320, 0, 171, 162, 127), + B_13_GRAVEL("minecraft:gravel", 13, "Gravel", 1440, 0, 103, 99, 99), + B_14_GOLD_ORE("minecraft:gold_ore", 14, "Gold Ore", 1560, 0, 112, 109, 98), + B_15_IRON_ORE("minecraft:iron_ore", 15, "Iron Ore", 1680, 0, 106, 102, 99), + B_16_COAL_ORE("minecraft:coal_ore", 16, "Coal Ore", 1800, 0, 91, 91, 91), + B_17_LOG("minecraft:log", 17, "Log", 1920, 0, 97, 76, 45), + B_18_LEAVES("minecraft:leaves", 18, "Leaves", 2040, 0, 29, 74, 9), + B_19_SPONGE("minecraft:sponge", 19, "Sponge", 2160, 0, 153, 150, 58), + B_20_GLASS("minecraft:glass", 20, "Glass", 2280, 0, 139, 169, 173), + B_21_LAPIS_ORE("minecraft:lapis_ore", 21, "Lapis Lazuli Ore", 0, 120, 78, 87, 104), + B_22_LAPIS_BLOCK("minecraft:lapis_block", 22, "Lapis Lazuli Block", 120, 120, 23, 53, 110), + B_23_DISPENSER("minecraft:dispenser", 23, "Dispenser", 240, 120, 91, 90, 90), + B_24_SANDSTONE("minecraft:sandstone", 24, "Sandstone", 360, 120, 171, 162, 126), + B_25_NOTEBLOCK("minecraft:noteblock", 25, "Note Block", 480, 120, 68, 45, 31), + B_26_BED("minecraft:bed", 26, "Bed", 600, 120, 142, 73, 65), + B_27_GOLDEN_RAIL("minecraft:golden_rail", 27, "Powered Rail", 720, 120, 134, 105, 70), + B_28_DETECTOR_RAIL("minecraft:detector_rail", 28, "Detector Rail", 840, 120, 119, 100, 85), + B_29_STICKY_PISTON("minecraft:sticky_piston", 29, "Sticky Piston", 960, 120, 90, 95, 76), + B_30_WEB("minecraft:web", 30, "Cobweb", 1080, 120, 158, 162, 163), + B_31_TALLGRASS("minecraft:tallgrass", 31, "Tall Grass", 1200, 120, 71, 109, 61), + B_32_DEADBUSH("minecraft:deadbush", 32, "Dead Bush", 1320, 120, 104, 77, 40), + B_33_PISTON("minecraft:piston", 33, "Piston", 1440, 120, 99, 89, 74), + B_34_PISTONARMCOLLISION("minecraft:pistonarmcollision", 34, "Piston Head", 1560, 120, 115, 98, 71), + B_35_WOOL("minecraft:wool", 35, "Wool", 1680, 120, 183, 185, 185), + //B_36_ELEMENT_0("minecraft:element_0", 36, "Unknown Element ", 1800, 120, 70, 62, 72), + B_37_YELLOW_FLOWER("minecraft:yellow_flower", 37, "Dandelion", 1920, 120, 151, 177, 45), + B_38_RED_FLOWER("minecraft:red_flower", 38, "Flower", 2040, 120, 122, 64, 37), + B_39_BROWN_MUSHROOM("minecraft:brown_mushroom", 39, "Brown Mushroom", 2160, 120, 151, 114, 90), + B_40_RED_MUSHROOM("minecraft:red_mushroom", 40, "Red Mushroom", 2280, 120, 212, 72, 67), + B_41_GOLD_BLOCK("minecraft:gold_block", 41, "Block of Gold", 0, 240, 192, 162, 48), + B_42_IRON_BLOCK("minecraft:iron_block", 42, "Block of Iron", 120, 240, 172, 171, 171), + B_43_DOUBLE_STONE_SLAB("minecraft:double_stone_slab", 43, "Double Stone Slab", 240, 240, 128, 128, 128), + B_44_STONE_SLAB("minecraft:stone_slab", 44, "Stone Slab", 360, 240, 135, 135, 136), + B_45_BRICK_BLOCK("minecraft:brick_block", 45, "Brick Block", 480, 240, 118, 76, 65), + B_46_TNT("minecraft:tnt", 46, "TNT", 600, 240, 132, 61, 56), + B_47_BOOKSHELF("minecraft:bookshelf", 47, "Bookshelf", 720, 240, 105, 85, 52), + B_48_MOSSY_COBBLESTONE("minecraft:mossy_cobblestone", 48, "Mossy Cobblestone", 840, 240, 86, 93, 74), + B_49_OBSIDIAN("minecraft:obsidian", 49, "Obsidian", 960, 240, 11, 8, 19), + B_50_TORCH("minecraft:torch", 50, "Torch", 1080, 240, 147, 121, 65), + B_51_FIRE("minecraft:fire", 51, "Fire", 1200, 240, 206, 126, 39), + B_52_MOB_SPAWNER("minecraft:mob_spawner", 52, "Spawner", 1320, 240, 28, 36, 48), + B_53_OAK_STAIRS("minecraft:oak_stairs", 53, "Oak Stairs", 1440, 240, 131, 105, 64), + B_54_CHEST("minecraft:chest", 54, "Chest", 1560, 240, 93, 69, 31), + B_55_REDSTONE_WIRE("minecraft:redstone_wire", 55, "Redstone Wire", 1680, 240, 48, 0, 0), + B_56_DIAMOND_ORE("minecraft:diamond_ore", 56, "Diamond Ore", 1800, 240, 98, 111, 110), + B_57_DIAMOND_BLOCK("minecraft:diamond_block", 57, "Block of Diamond", 1920, 240, 75, 185, 178), + B_58_CRAFTING_TABLE("minecraft:crafting_table", 58, "Crafting Table", 2040, 240, 96, 71, 44), + B_59_WHEAT("minecraft:wheat", 59, "Wheat Crops", 2160, 240, 169, 153, 74), + B_60_FARMLAND("minecraft:farmland", 60, "Farmland", 2280, 240, 108, 77, 53), + B_61_FURNACE("minecraft:furnace", 61, "Furnace", 0, 360, 82, 82, 82), + B_62_LIT_FURNACE("minecraft:lit_furnace", 62, "Burning Lit Furnace", 120, 360, 91, 88, 82), + B_63_STANDING_SIGN("minecraft:standing_sign", 63, "Oak Standing Sign", 240, 360, 107, 88, 53), + B_64_OAK_DOOR("minecraft:oak_door", 64, "Oak Door", 360, 360, 107, 84, 50), + B_65_LADDER("minecraft:ladder", 65, "Ladder", 480, 360, 98, 76, 43), + B_66_RAIL("minecraft:rail", 66, "Rail", 600, 360, 127, 115, 95), + B_67_STONE_STAIRS("minecraft:stone_stairs", 67, "Cobblestone Stairs", 720, 360, 103, 102, 104), + B_68_WALL_SIGN("minecraft:wall_sign", 68, "Oak Wall Sign", 840, 360, 115, 94, 56), + B_69_LEVER("minecraft:lever", 69, "Lever", 960, 360, 98, 96, 94), + B_70_STONE_PRESSURE_PLATE("minecraft:stone_pressure_plate", 70, "Stone Pressure Plate", 1080, 360, 117, 117, 117), + B_71_IRON_DOOR("minecraft:iron_door", 71, "Iron Door", 1200, 360, 153, 153, 154), + B_72_WOODEN_PRESSURE_PLATE("minecraft:wooden_pressure_plate", 72, "Oak Pressure Plate", 1320, 360, 148, 119, 71), + B_73_REDSTONE_ORE("minecraft:redstone_ore", 73, "Redstone Ore", 1440, 360, 104, 84, 84), + B_74_LIT_REDSTONE_ORE("minecraft:lit_redstone_ore", 74, "Glowing Redstone Ore", 1560, 360, 104, 84, 84), + B_75_UNLIT_REDSTONE_TORCH("minecraft:unlit_redstone_torch", 75, "Unlit Redstone Torch", 1680, 360, 98, 64, 40), + B_76_REDSTONE_TORCH("minecraft:redstone_torch", 76, "Redstone Torch", 1800, 360, 172, 64, 35), + B_77_STONE_BUTTON("minecraft:stone_button", 77, "Stone Button", 1920, 360, 102, 102, 102), + B_78_SNOW_LAYER("minecraft:snow_layer", 78, "Top Snow", 2040, 360, 226, 231, 231), + B_79_ICE("minecraft:ice", 79, "Ice", 2160, 360, 114, 144, 199), + B_80_SNOW("minecraft:snow", 80, "Snow", 2280, 360, 195, 199, 199), + B_81_CACTUS("minecraft:cactus", 81, "Cactus", 0, 480, 67, 100, 33), + B_82_CLAY("minecraft:clay", 82, "Clay", 120, 480, 126, 130, 140), + B_83_REEDS("minecraft:reeds", 83, "Sugar Cane", 240, 480, 71, 143, 40), + B_84_JUKEBOX("minecraft:jukebox", 84, "Jukebox", 360, 480, 70, 47, 33), + B_85_FENCE("minecraft:fence", 85, "Oak Fence", 480, 480, 125, 100, 60), + B_86_PUMPKIN("minecraft:pumpkin", 86, "Pumpkin", 600, 480, 153, 90, 18), + B_87_NETHERRACK("minecraft:netherrack", 87, "Netherrack", 720, 480, 76, 29, 29), + B_88_SOUL_SAND("minecraft:soul_sand", 88, "Soul Sand", 840, 480, 63, 48, 39), + B_89_GLOWSTONE("minecraft:glowstone", 89, "Glowstone", 960, 480, 134, 102, 66), + B_90_PORTAL("minecraft:portal", 90, "Portal", 1080, 480, 112, 15, 228), + B_91_LIT_PUMPKIN("minecraft:lit_pumpkin", 91, "Jack o'Lantern", 1200, 480, 158, 100, 26), + B_92_CAKE("minecraft:cake", 92, "Cake", 1320, 480, 184, 152, 137), + B_93_UNPOWERED_REPEATER("minecraft:unpowered_repeater", 93, "Redstone Repeater", 1440, 480, 128, 122, 119), + B_94_POWERED_REPEATER("minecraft:powered_repeater", 94, "Active Redstone Repeater", 1560, 480, 145, 121, 116), + B_95_INVISIBLEBEDROCK("minecraft:invisiblebedrock", 95, "Invisible Bedrock", -1, 0, -1, 0, 0), + B_96_WOODEN_TRAPDOOR("minecraft:wooden_trapdoor", 96, "Oak Trapdoor", 1680, 480, 96, 77, 43), + B_97_MONSTER_EGG("minecraft:monster_egg", 97, "Monster Egg", 1800, 480, 98, 98, 98), + B_98_STONEBRICK("minecraft:stonebrick", 98, "Stone Bricks", 1920, 480, 96, 95, 96), + B_99_BROWN_MUSHROOM_BLOCK("minecraft:brown_mushroom_block", 99, "Brown Mushroom Block", 2040, 480, 118, 88, 64), + B_100_RED_MUSHROOM_BLOCK("minecraft:red_mushroom_block", 100, "Red Mushroom Block", 2160, 480, 158, 36, 35), + B_101_IRON_BARS("minecraft:iron_bars", 101, "Iron Bars", 2280, 480, 102, 103, 101), + B_102_GLASS_PANE("minecraft:glass_pane", 102, "Glass Pane", 0, 600, 150, 178, 181), + B_103_MELON_BLOCK("minecraft:melon_block", 103, "Melon", 120, 600, 88, 114, 23), + B_104_PUMPKIN_STEM("minecraft:pumpkin_stem", 104, "Pumpkin Stem", 240, 600, 106, 94, 12), + B_105_MELON_STEM("minecraft:melon_stem", 105, "Melon Stem", 360, 600, 106, 94, 12), + B_106_VINE("minecraft:vine", 106, "Vines", 480, 600, 32, 82, 10), + B_107_FENCE_GATE("minecraft:fence_gate", 107, "Oak Fence Gate", 600, 600, 128, 103, 61), + B_108_BRICK_STAIRS("minecraft:brick_stairs", 108, "Brick Stairs", 720, 600, 122, 79, 68), + B_109_STONE_BRICK_STAIRS("minecraft:stone_brick_stairs", 109, "Stone Brick Stairs", 840, 600, 99, 98, 100), + B_110_MYCELIUM("minecraft:mycelium", 110, "Mycelium", 960, 600, 88, 71, 64), + B_111_WATERLILY("minecraft:waterlily", 111, "Lily Pad", 1080, 600, 16, 65, 24), + B_112_NETHER_BRICK_BLOCK("minecraft:nether_brick_block", 112, "Nether Brick Block", 1200, 600, 34, 17, 20), + B_113_NETHER_BRICK_FENCE("minecraft:nether_brick_fence", 113, "Nether Brick Fence", 1320, 600, 34, 17, 20), + B_114_NETHER_BRICK_STAIRS("minecraft:nether_brick_stairs", 114, "Nether Brick Stairs", 1440, 600, 35, 17, 21), + B_115_NETHER_WART("minecraft:nether_wart", 115, "Nether Wart", 1560, 600, 114, 17, 17), + B_116_ENCHANTING_TABLE("minecraft:enchanting_table", 116, "Enchantment Table", 1680, 600, 88, 76, 69), + B_117_BREWING_STAND("minecraft:brewing_stand", 117, "Brewing Stand", 1800, 600, 93, 82, 70), + B_118_CAULDRON("minecraft:cauldron", 118, "Cauldron", 1920, 600, 56, 55, 56), + B_119_END_PORTAL("minecraft:end_portal", 119, "End Portal", 2040, 600, 7, 14, 24), + B_120_END_PORTAL_FRAME("minecraft:end_portal_frame", 120, "End Portal Frame", 2160, 600, 100, 116, 89), + B_121_END_STONE("minecraft:end_stone", 121, "End Stone", 2280, 600, 172, 174, 124), + B_122_DRAGON_EGG("minecraft:dragon_egg", 122, "Dragon Egg", 0, 720, 10, 7, 12), + B_123_REDSTONE_LAMP("minecraft:redstone_lamp", 123, "Redstone Lamp ", 120, 720, 73, 42, 23), + B_124_LIT_REDSTONE_LAMP("minecraft:lit_redstone_lamp", 124, "Redstone Lamp ", 240, 720, 110, 78, 46), + B_125_DROPPER("minecraft:dropper", 125, "Dropper", 360, 720, 91, 90, 90), + B_126_ACTIVATOR_RAIL("minecraft:activator_rail", 126, "Activator Rail", 480, 720, 111, 83, 70), + B_127_COCOA("minecraft:cocoa", 127, "Cocoa", 600, 720, 116, 69, 31), + B_128_SANDSTONE_STAIRS("minecraft:sandstone_stairs", 128, "Sandstone Stairs", 720, 720, 177, 168, 132), + B_129_EMERALD_ORE("minecraft:emerald_ore", 129, "Emerald Ore", 840, 720, 92, 107, 97), + B_130_ENDER_CHEST("minecraft:ender_chest", 130, "Ender Chest", 960, 720, 26, 38, 38), + B_131_TRIPWIRE_HOOK("minecraft:tripwire_hook", 131, "Tripwire Hook", 1080, 720, 124, 107, 81), + B_132_TRIPWIRE("minecraft:tripwire", 132, "Tripwire", 1200, 720, 142, 142, 142), + B_133_EMERALD_BLOCK("minecraft:emerald_block", 133, "Block of Emerald", 1320, 720, 32, 159, 68), + B_134_SPRUCE_STAIRS("minecraft:spruce_stairs", 134, "Spruce Stairs", 1440, 720, 93, 68, 39), + B_135_BIRCH_STAIRS("minecraft:birch_stairs", 135, "Birch Stairs", 1560, 720, 155, 142, 99), + B_136_JUNGLE_STAIRS("minecraft:jungle_stairs", 136, "Jungle Stairs", 1680, 720, 129, 93, 65), + B_137_IMPULSE_COMMAND_BLOCK("minecraft:impulse_command_block", 137, "Impulse Command Block", 1800, 720, 140, 105, 83), + B_138_BEACON("minecraft:beacon", 138, "Beacon", 1920, 720, 103, 151, 152), + B_139_COBBLESTONE_WALL("minecraft:cobblestone_wall", 139, "Cobblestone Wall", 2040, 720, 99, 99, 100), + B_140_FLOWER_POT("minecraft:flower_pot", 140, "Flower Pot", 2160, 720, 94, 52, 41), + B_141_CARROTS("minecraft:carrots", 141, "Carrots", 2280, 720, 78, 123, 37), + B_142_POTATOES("minecraft:potatoes", 142, "Potatoes", 0, 840, 96, 161, 49), + B_143_WOODEN_BUTTON("minecraft:wooden_button", 143, "Oak Button", 120, 840, 134, 108, 65), + B_144_SKULL("minecraft:skull", 144, "Mob head", 240, 840, 61, 42, 28), + B_145_ANVIL("minecraft:anvil", 145, "Anvil", 360, 840, 57, 57, 57), + B_146_TRAPPED_CHEST("minecraft:trapped_chest", 146, "Trapped Chest", 480, 840, 93, 69, 31), + B_147_LIGHT_WEIGHTED_PRESSURE_PLATE("minecraft:light_weighted_pressure_plate", 147, "Weighted Pressure Plate ", 600, 840, 230, 197, 61), + B_148_HEAVY_WEIGHTED_PRESSURE_PLATE("minecraft:heavy_weighted_pressure_plate", 148, "Weighted Pressure Plate ", 720, 840, 208, 208, 208), + B_149_UNPOWERED_COMPARATOR("minecraft:unpowered_comparator", 149, "Redstone Comparator ", 840, 840, 132, 123, 119), + B_150_POWERED_COMPARATOR("minecraft:powered_comparator", 150, "Redstone Comparator ", 960, 840, 149, 122, 116), + B_151_DAYLIGHT_DETECTOR("minecraft:daylight_detector", 151, "Daylight Sensor", 1080, 840, 87, 76, 58), + B_152_REDSTONE_BLOCK("minecraft:redstone_block", 152, "Block of Redstone", 1200, 840, 138, 19, 4), + B_153_QUARTZ_ORE("minecraft:quartz_ore", 153, "Nether Quartz Ore", 1320, 840, 91, 50, 48), + B_154_HOPPER("minecraft:hopper", 154, "Hopper", 1440, 840, 60, 59, 60), + B_155_QUARTZ_BLOCK("minecraft:quartz_block", 155, "Block of Quartz", 1560, 840, 184, 180, 174), + B_156_QUARTZ_STAIRS("minecraft:quartz_stairs", 156, "Quartz Stairs", 1680, 840, 191, 186, 182), + B_157_DOUBLE_WOODEN_SLAB("minecraft:double_wooden_slab", 157, "Wooden Double Slab", 1800, 840, 126, 102, 61), + B_158_WOODEN_SLAB("minecraft:wooden_slab", 158, "Wooden Slab", 1920, 840, 133, 107, 64), + B_159_STAINED_HARDENED_CLAY("minecraft:stained_hardened_clay", 159, "Terracotta", 2040, 840, 164, 139, 126), + B_160_STAINED_GLASS_PANE("minecraft:stained_glass_pane", 160, "Stained Glass Pane", 2160, 840, 202, 202, 202), + B_161_LEAVES2("minecraft:leaves2", 161, "Acacia Leaves", 2280, 840, 29, 74, 9), + B_162_LOG2("minecraft:log2", 162, "Acacia Log", 0, 960, 94, 73, 59), + B_163_ACACIA_STAIRS("minecraft:acacia_stairs", 163, "Acacia Stairs", 120, 960, 136, 73, 41), + B_164_DARK_OAK_STAIRS("minecraft:dark_oak_stairs", 164, "Dark Oak Stairs", 240, 960, 54, 34, 16), + B_165_SLIME("minecraft:slime", 165, "Slime Block", 360, 960, 88, 152, 73), + B_166_GLOW_STICK("minecraft:glow_stick", 166, "Glow Stick", 480, 960, 175, 176, 178), + B_167_IRON_TRAPDOOR("minecraft:iron_trapdoor", 167, "Iron Trapdoor", 600, 960, 162, 161, 161), + B_168_PRISMARINE("minecraft:prismarine", 168, "Prismarine", 720, 960, 78, 128, 116), + B_169_SEALANTERN("minecraft:sealantern", 169, "Sea Lantern", 840, 960, 133, 155, 148), + B_170_HAY_BLOCK("minecraft:hay_block", 170, "Hay Bale", 960, 960, 130, 107, 22), + B_171_CARPET("minecraft:carpet", 171, "Carpet", 1080, 960, 218, 220, 221), + B_172_HARDENED_CLAY("minecraft:hardened_clay", 172, "Terracotta", 1200, 960, 120, 74, 54), + B_173_COAL_BLOCK("minecraft:coal_block", 173, "Block of Coal", 1320, 960, 12, 12, 12), + B_174_PACKED_ICE("minecraft:packed_ice", 174, "Packed Ice", 1440, 960, 112, 142, 198), + B_175_DOUBLE_PLANT("minecraft:double_plant", 175, "Sunflower", 1560, 960, 118, 154, 37), + B_176_STANDING_BANNER("minecraft:standing_banner", 176, "Standing Banner", 1680, 960, 140, 140, 138), + B_177_WALL_BANNER("minecraft:wall_banner", 177, "Wall Banner", 1800, 960, 142, 141, 140), + B_178_DAYLIGHT_DETECTOR_INVERTED("minecraft:daylight_detector_inverted", 178, "Inverted Daylight Detector", 1920, 960, 75, 73, 67), + B_179_RED_SANDSTONE("minecraft:red_sandstone", 179, "Red Sandstone", 2040, 960, 145, 77, 23), + B_180_RED_SANDSTONE_STAIRS("minecraft:red_sandstone_stairs", 180, "Red Sandstone Stairs", 2160, 960, 149, 80, 24), + B_181_DOUBLE_STONE_SLAB2("minecraft:double_stone_slab2", 181, "Double Red Sandstone Slab", 2280, 960, 145, 77, 23), + B_182_STONE_SLAB2("minecraft:stone_slab2", 182, "Red Sandstone Slab", 0, 1080, 153, 82, 25), + B_183_SPRUCE_FENCE_GATE("minecraft:spruce_fence_gate", 183, "Spruce Fence Gate", 120, 1080, 90, 67, 38), + B_184_BIRCH_FENCE_GATE("minecraft:birch_fence_gate", 184, "Birch Fence Gate", 240, 1080, 153, 139, 96), + B_185_JUNGLE_FENCE_GATE("minecraft:jungle_fence_gate", 185, "Jungle Fence Gate", 360, 1080, 127, 91, 63), + B_186_DARK_OAK_FENCE_GATE("minecraft:dark_oak_fence_gate", 186, "Dark Oak Fence Gate", 480, 1080, 52, 33, 15), + B_187_ACACIA_FENCE_GATE("minecraft:acacia_fence_gate", 187, "Acacia Fence Gate", 600, 1080, 134, 72, 40), + B_188_REPEATING_COMMAND_BLOCK("minecraft:repeating_command_block", 188, "Repeating Command Block", 720, 1080, 100, 86, 135), + B_189_CHAIN_COMMAND_BLOCK("minecraft:chain_command_block", 189, "Chain Command Block", 840, 1080, 102, 127, 116), + B_190_HARD_GLASS_PANE("minecraft:hard_glass_pane", 190, "Hardened Glass Pane", 960, 1080, 166, 195, 187), + B_191_HARD_STAINED_GLASS_PANE("minecraft:hard_stained_glass_pane", 191, "Hardened Stained Glass Pane", 1080, 1080, 198, 198, 198), + B_192_CHEMICAL_HEAT("minecraft:chemical_heat", 192, "Heat Block", 1200, 1080, 61, 45, 42), + B_193_SPRUCE_DOOR("minecraft:spruce_door", 193, "Spruce Door", 1320, 1080, 83, 63, 38), + B_194_BIRCH_DOOR("minecraft:birch_door", 194, "Birch Door", 1440, 1080, 163, 153, 119), + B_195_JUNGLE_DOOR("minecraft:jungle_door", 195, "Jungle Door", 1560, 1080, 125, 91, 64), + B_196_ACACIA_DOOR("minecraft:acacia_door", 196, "Acacia Door", 1680, 1080, 127, 72, 45), + B_197_DARK_OAK_DOOR("minecraft:dark_oak_door", 197, "Dark Oak Door", 1800, 1080, 58, 39, 19), + B_198_GRASS_PATH("minecraft:grass_path", 198, "Grass Path", 1920, 1080, 115, 88, 54), + B_199_FRAME("minecraft:frame", 199, "Item Frame", 2040, 1080, 125, 92, 60), + B_200_CHORUS_FLOWER("minecraft:chorus_flower", 200, "Chorus Flower", 2160, 1080, 127, 105, 127), + B_201_PURPUR_BLOCK("minecraft:purpur_block", 201, "Purpur Block", 2280, 1080, 133, 98, 133), + B_202_COLORED_TORCH_RG("minecraft:colored_torch_rg", 202, "Red Torch", 0, 1200, 137, 76, 53), + B_203_PURPUR_STAIRS("minecraft:purpur_stairs", 203, "Purpur Stairs", 120, 1200, 137, 102, 138), + B_204_COLORED_TORCH_BP("minecraft:colored_torch_bp", 204, "Blue Torch", 240, 1200, 97, 89, 97), + B_205_UNDYED_SHULKER_BOX("minecraft:undyed_shulker_box", 205, "Shulker Box ", 360, 1200, 100, 70, 100), + B_206_END_BRICKS("minecraft:end_bricks", 206, "End Stone Bricks", 480, 1200, 171, 175, 126), + B_207_FROSTED_ICE("minecraft:frosted_ice", 207, "Frosted Ice", 600, 1200, 114, 144, 199), + B_208_END_ROD("minecraft:end_rod", 208, "End Rod", 720, 1200, 169, 162, 153), + B_209_END_GATEWAY("minecraft:end_gateway", 209, "End Gateway", 840, 1200, 6, 15, 24), + B_213_MAGMA("minecraft:magma", 213, "Magma Block", 960, 1200, 112, 49, 24), + B_214_NETHER_WART_BLOCK("minecraft:nether_wart_block", 214, "Nether Wart Block", 1080, 1200, 90, 2, 2), + B_215_RED_NETHER_BRICK("minecraft:red_nether_brick", 215, "Red Nether Brick", 1200, 1200, 54, 5, 7), + B_216_BONE_BLOCK("minecraft:bone_block", 216, "Bone Block", 1320, 1200, 174, 171, 155), + B_217_STRUCTURE_VOID("minecraft:structure_void", 217, "Structure Void", 1440, 1200, 203, 0, 0), + B_218_SHULKER_BOX("minecraft:shulker_box", 218, "Shulker Box", 1560, 1200, 135, 139, 140), + B_219_PURPLE_GLAZED_TERRACOTTA("minecraft:purple_glazed_terracotta", 219, "Purple Glazed Terracotta", 1680, 1200, 87, 38, 122), + B_220_WHITE_GLAZED_TERRACOTTA("minecraft:white_glazed_terracotta", 220, "White Glazed Terracotta", 1800, 1200, 150, 168, 161), + B_221_ORANGE_GLAZED_TERRACOTTA("minecraft:orange_glazed_terracotta", 221, "Orange Glazed Terracotta", 1920, 1200, 123, 117, 74), + B_222_MAGENTA_GLAZED_TERRACOTTA("minecraft:magenta_glazed_terracotta", 222, "Magenta Glazed Terracotta", 2040, 1200, 165, 79, 153), + B_223_LIGHT_BLUE_GLAZED_TERRACOTTA("minecraft:light_blue_glazed_terracotta", 223, "Light Blue Glazed Terracotta", 2160, 1200, 74, 130, 167), + B_224_YELLOW_GLAZED_TERRACOTTA("minecraft:yellow_glazed_terracotta", 224, "Yellow Glazed Terracotta", 2280, 1200, 186, 152, 71), + B_225_LIME_GLAZED_TERRACOTTA("minecraft:lime_glazed_terracotta", 225, "Lime Glazed Terracotta", 0, 1320, 128, 156, 44), + B_226_PINK_GLAZED_TERRACOTTA("minecraft:pink_glazed_terracotta", 226, "Pink Glazed Terracotta", 120, 1320, 186, 122, 145), + B_227_GRAY_GLAZED_TERRACOTTA("minecraft:gray_glazed_terracotta", 227, "Gray Glazed Terracotta", 240, 1320, 65, 71, 74), + B_228_SILVER_GLAZED_TERRACOTTA("minecraft:silver_glazed_terracotta", 228, "Light Gray Glazed Terracotta", 360, 1320, 114, 131, 134), + B_229_CYAN_GLAZED_TERRACOTTA("minecraft:cyan_glazed_terracotta", 229, "Cyan Glazed Terracotta", 480, 1320, 41, 94, 100), + B_231_BLUE_GLAZED_TERRACOTTA("minecraft:blue_glazed_terracotta", 231, "Blue Glazed Terracotta", 600, 1320, 37, 51, 111), + B_232_BROWN_GLAZED_TERRACOTTA("minecraft:brown_glazed_terracotta", 232, "Brown Glazed Terracotta", 720, 1320, 95, 84, 69), + B_233_GREEN_GLAZED_TERRACOTTA("minecraft:green_glazed_terracotta", 233, "Green Glazed Terracotta", 840, 1320, 93, 113, 54), + B_234_RED_GLAZED_TERRACOTTA("minecraft:red_glazed_terracotta", 234, "Red Glazed Terracotta", 960, 1320, 144, 47, 42), + B_235_BLACK_GLAZED_TERRACOTTA("minecraft:black_glazed_terracotta", 235, "Black Glazed Terracotta", 1080, 1320, 53, 23, 25), + B_236_CONCRETE("minecraft:concrete", 236, "Concrete", 1200, 1320, 162, 167, 167), + B_237_CONCRETEPOWDER("minecraft:concretepowder", 237, "Concrete Powder", 1320, 1320, 177, 178, 178), + B_238_CHEMISTRY_TABLE("minecraft:chemistry_table", 238, "Compound Creator", 1440, 1320, 111, 103, 89), + B_239_UNDERWATER_TORCH("minecraft:underwater_torch", 239, "Underwater Torch", 1560, 1320, 80, 120, 110), + B_240_CHORUS_PLANT("minecraft:chorus_plant", 240, "Chorus Plant", 1680, 1320, 72, 44, 73), + B_241_STAINED_GLASS("minecraft:stained_glass", 241, "Stained Glass", 1800, 1320, 202, 202, 204), + B_242_CAMERA("minecraft:camera", 242, "Camera", 1920, 1320, 63, 51, 34), + B_243_PODZOL("minecraft:podzol", 243, "Podzol", 2040, 1320, 87, 61, 35), + B_244_BEETROOT("minecraft:beetroot", 244, "Beetroots", 2160, 1320, 101, 122, 40), + B_245_STONECUTTER("minecraft:stonecutter", 245, "Stonecutter", 2280, 1320, 90, 90, 90), + B_246_GLOWINGOBSIDIAN("minecraft:glowingobsidian", 246, "Glowing Obsidian", 0, 1440, 62, 2, 10), + B_247_NETHERREACTOR("minecraft:netherreactor", 247, "Nether Reactor Core", 120, 1440, 94, 134, 142), + B_248_INFO_UPDATE("minecraft:info_update", 248, "Update Game Block ", 240, 1440, 91, 88, 46), + B_249_INFO_UPDATE2("minecraft:info_update2", 249, "Update Game Block ", 360, 1440, 91, 87, 46), + B_250_MOVINGBLOCK("minecraft:movingblock", 250, "Block moved by Piston", -1, 0, -1, 0, 0), + B_251_OBSERVER("minecraft:observer", 251, "Observer", 480, 1440, 72, 72, 73), + B_252_STRUCTURE_BLOCK("minecraft:structure_block", 252, "Structure Block", 600, 1440, 68, 57, 69), + B_253_HARD_GLASS("minecraft:hard_glass", 253, "Hardened Glass", 720, 1440, 164, 193, 183), + B_254_HARD_STAINED_GLASS("minecraft:hard_stained_glass", 254, "Hardened Stained Glass", 840, 1440, 194, 194, 194), + B_255_RESERVED6("minecraft:reserved6", 255, "reserved6", 960, 1440, 91, 88, 46), + B_256_("minecraft:", 256, "", -1, 0, -1, 0, 0), + B_257_PRISMARINE_STAIRS("minecraft:prismarine_stairs", 257, "Prismarine Stairs", 1080, 1440, 80, 131, 119), + B_258_DARK_PRISMARINE_STAIRS("minecraft:dark_prismarine_stairs", 258, "Dark Prismarine Stairs", 1200, 1440, 42, 74, 62), + B_259_PRISMARINE_BRICKS_STAIRS("minecraft:prismarine_bricks_stairs", 259, "Prismarine Brick Stairs", 1320, 1440, 80, 138, 129), + B_260_STRIPPED_SPRUCE_LOG("minecraft:stripped_spruce_log", 260, "Stripped Spruce Log", 1440, 1440, 87, 67, 39), + B_261_STRIPPED_BIRCH_LOG("minecraft:stripped_birch_log", 261, "Stripped Birch Log", 1560, 1440, 152, 136, 91), + B_262_STRIPPED_JUNGLE_LOG("minecraft:stripped_jungle_log", 262, "Stripped Jungle Log", 1680, 1440, 132, 101, 65), + B_263_STRIPPED_ACACIA_LOG("minecraft:stripped_acacia_log", 263, "Stripped Acacia Log", 1800, 1440, 134, 72, 44), + B_264_STRIPPED_DARK_OAK_LOG("minecraft:stripped_dark_oak_log", 264, "Stripped Dark Oak Log", 1920, 1440, 66, 50, 31), + B_265_STRIPPED_OAK_LOG("minecraft:stripped_oak_log", 265, "Stripped Oak Log", 2040, 1440, 133, 108, 64), + B_266_BLUE_ICE("minecraft:blue_ice", 266, "Blue Ice", 2160, 1440, 95, 133, 196), + //B_267_ELEMENT_1("minecraft:element_1", 267, "Hydrogen", 2280, 1440, 117, 145, 87), +//B_268_ELEMENT_2("minecraft:element_2", 268, "Helium", 0, 1560, 155, 116, 182), +//B_269_ELEMENT_3("minecraft:element_3", 269, "Lithium", 120, 1560, 101, 123, 181), +//B_270_ELEMENT_4("minecraft:element_4", 270, "Beryllium", 240, 1560, 92, 148, 162), +//B_271_ELEMENT_5("minecraft:element_5", 271, "Boron", 360, 1560, 158, 130, 128), +//B_272_ELEMENT_6("minecraft:element_6", 272, "Carbon", 480, 1560, 116, 144, 86), +//B_273_ELEMENT_7("minecraft:element_7", 273, "Nitrogen", 600, 1560, 117, 145, 87), +//B_274_ELEMENT_8("minecraft:element_8", 274, "Oxygen", 720, 1560, 117, 145, 87), +//B_275_ELEMENT_9("minecraft:element_9", 275, "Fluorine", 840, 1560, 185, 136, 86), +//B_276_ELEMENT_10("minecraft:element_10", 276, "Neon", 960, 1560, 155, 117, 182), +//B_277_ELEMENT_11("minecraft:element_11", 277, "Sodium", 1080, 1560, 107, 127, 182), +//B_278_ELEMENT_12("minecraft:element_12", 278, "Magnesium", 1200, 1560, 95, 149, 163), +//B_279_ELEMENT_13("minecraft:element_13", 279, "Aluminum", 1320, 1560, 154, 150, 135), +//B_280_ELEMENT_14("minecraft:element_14", 280, "Silicon", 1440, 1560, 158, 130, 129), +//B_281_ELEMENT_15("minecraft:element_15", 281, "Phosphorus", 1560, 1560, 117, 145, 87), +//B_282_ELEMENT_16("minecraft:element_16", 282, "Sulfur", 1680, 1560, 117, 145, 87), +//B_283_ELEMENT_17("minecraft:element_17", 283, "Chlorine", 1800, 1560, 183, 136, 87), +//B_284_ELEMENT_18("minecraft:element_18", 284, "Argon", 1920, 1560, 155, 115, 182), +//B_285_ELEMENT_19("minecraft:element_19", 285, "Potassium", 2040, 1560, 101, 123, 181), +//B_286_ELEMENT_20("minecraft:element_20", 286, "Calcium", 2160, 1560, 90, 148, 162), +//B_287_ELEMENT_21("minecraft:element_21", 287, "Scandium", 2280, 1560, 127, 127, 127), +//B_288_ELEMENT_22("minecraft:element_22", 288, "Titanium", 0, 1680, 127, 127, 127), +//B_289_ELEMENT_23("minecraft:element_23", 289, "Vanadium", 120, 1680, 126, 126, 126), +//B_290_ELEMENT_24("minecraft:element_24", 290, "Chromium", 240, 1680, 128, 128, 128), +//B_291_ELEMENT_25("minecraft:element_25", 291, "Manganese", 360, 1680, 130, 130, 130), +//B_292_ELEMENT_26("minecraft:element_26", 292, "Iron", 480, 1680, 130, 130, 130), +//B_293_ELEMENT_27("minecraft:element_27", 293, "Cobalt", 600, 1680, 127, 127, 127), +//B_294_ELEMENT_28("minecraft:element_28", 294, "Nickel", 720, 1680, 128, 128, 128), +//B_295_ELEMENT_29("minecraft:element_29", 295, "Copper", 840, 1680, 128, 128, 128), +//B_296_ELEMENT_30("minecraft:element_30", 296, "Zinc", 960, 1680, 129, 129, 129), +//B_297_ELEMENT_31("minecraft:element_31", 297, "Gallium", 1080, 1680, 155, 151, 136), +//B_298_ELEMENT_32("minecraft:element_32", 298, "Germanium", 1200, 1680, 160, 134, 132), +//B_299_ELEMENT_33("minecraft:element_33", 299, "Arsenic", 1320, 1680, 160, 133, 132), +//B_300_ELEMENT_34("minecraft:element_34", 300, "Selenium", 1440, 1680, 122, 148, 94), +//B_301_ELEMENT_35("minecraft:element_35", 301, "Bromine", 1560, 1680, 184, 138, 93), +//B_302_ELEMENT_36("minecraft:element_36", 302, "Krypton", 1680, 1680, 155, 114, 182), +//B_303_ELEMENT_37("minecraft:element_37", 303, "Rubidium", 1800, 1680, 108, 128, 182), +//B_304_ELEMENT_38("minecraft:element_38", 304, "Strontium", 1920, 1680, 88, 147, 161), +//B_305_ELEMENT_39("minecraft:element_39", 305, "Yttrium", 2040, 1680, 125, 125, 125), +//B_306_ELEMENT_40("minecraft:element_40", 306, "Zirconium", 2160, 1680, 128, 128, 128), +//B_307_ELEMENT_41("minecraft:element_41", 307, "Niobium", 2280, 1680, 130, 130, 130), +//B_308_ELEMENT_42("minecraft:element_42", 308, "Molybdenum", 0, 1800, 130, 130, 130), +//B_309_ELEMENT_43("minecraft:element_43", 309, "Technetium", 120, 1800, 127, 127, 127), +//B_310_ELEMENT_44("minecraft:element_44", 310, "Ruthenium", 240, 1800, 130, 130, 130), +//B_311_ELEMENT_45("minecraft:element_45", 311, "Rhodium", 360, 1800, 130, 130, 130), +//B_312_ELEMENT_46("minecraft:element_46", 312, "Palladium", 480, 1800, 130, 130, 130), +//B_313_ELEMENT_47("minecraft:element_47", 313, "Silver", 600, 1800, 131, 131, 131), +//B_314_ELEMENT_48("minecraft:element_48", 314, "Cadmium", 720, 1800, 129, 129, 129), +//B_315_ELEMENT_49("minecraft:element_49", 315, "Indium", 840, 1800, 155, 150, 135), +//B_316_ELEMENT_50("minecraft:element_50", 316, "Tin", 960, 1800, 155, 150, 135), +//B_317_ELEMENT_51("minecraft:element_51", 317, "Antimony", 1080, 1800, 159, 133, 131), +//B_318_ELEMENT_52("minecraft:element_52", 318, "Tellurium", 1200, 1800, 160, 133, 132), +//B_319_ELEMENT_53("minecraft:element_53", 319, "Iodine", 1320, 1800, 183, 135, 86), +//B_320_ELEMENT_54("minecraft:element_54", 320, "Xenon", 1440, 1800, 155, 116, 182), +//B_321_ELEMENT_55("minecraft:element_55", 321, "Cesium", 1560, 1800, 106, 126, 181), +//B_322_ELEMENT_56("minecraft:element_56", 322, "Barium", 1680, 1800, 93, 149, 162), +//B_323_ELEMENT_57("minecraft:element_57", 323, "Lanthanum", 1800, 1800, 181, 138, 175), +//B_324_ELEMENT_58("minecraft:element_58", 324, "Cerium", 1920, 1800, 181, 139, 175), +//B_325_ELEMENT_59("minecraft:element_59", 325, "Praseodymium", 2040, 1800, 181, 138, 175), +//B_326_ELEMENT_60("minecraft:element_60", 326, "Neodymium", 2160, 1800, 181, 140, 175), +//B_327_ELEMENT_61("minecraft:element_61", 327, "Promethium", 2280, 1800, 181, 138, 175), +//B_328_ELEMENT_62("minecraft:element_62", 328, "Samarium", 0, 1920, 181, 139, 175), +//B_329_ELEMENT_63("minecraft:element_63", 329, "Europium", 120, 1920, 181, 139, 175), +//B_330_ELEMENT_64("minecraft:element_64", 330, "Gadolinium", 240, 1920, 181, 139, 175), +//B_331_ELEMENT_65("minecraft:element_65", 331, "Terbium", 360, 1920, 181, 139, 175), +//B_332_ELEMENT_66("minecraft:element_66", 332, "Dysprosium", 480, 1920, 181, 140, 175), +//B_333_ELEMENT_67("minecraft:element_67", 333, "Holmium", 600, 1920, 181, 138, 175), +//B_334_ELEMENT_68("minecraft:element_68", 334, "Erbium", 720, 1920, 181, 138, 175), +//B_335_ELEMENT_69("minecraft:element_69", 335, "Thulium", 840, 1920, 181, 138, 175), +//B_336_ELEMENT_70("minecraft:element_70", 336, "Ytterbium", 960, 1920, 181, 138, 175), +//B_337_ELEMENT_71("minecraft:element_71", 337, "Lutetium", 1080, 1920, 181, 137, 174), +//B_338_ELEMENT_72("minecraft:element_72", 338, "Hafnium", 1200, 1920, 129, 129, 129), +//B_339_ELEMENT_73("minecraft:element_73", 339, "Tantalum", 1320, 1920, 129, 129, 129), +//B_340_ELEMENT_74("minecraft:element_74", 340, "Tungsten", 1440, 1920, 127, 127, 127), +//B_341_ELEMENT_75("minecraft:element_75", 341, "Rhenium", 1560, 1920, 131, 131, 131), +//B_342_ELEMENT_76("minecraft:element_76", 342, "Osmium", 1680, 1920, 129, 129, 129), +//B_343_ELEMENT_77("minecraft:element_77", 343, "Iridium", 1800, 1920, 127, 127, 127), +//B_344_ELEMENT_78("minecraft:element_78", 344, "Platinum", 1920, 1920, 128, 128, 128), +//B_345_ELEMENT_79("minecraft:element_79", 345, "Gold", 2040, 1920, 129, 129, 129), +//B_346_ELEMENT_80("minecraft:element_80", 346, "Mercury", 2160, 1920, 131, 131, 131), +//B_347_ELEMENT_81("minecraft:element_81", 347, "Thallium", 2280, 1920, 154, 149, 134), +//B_348_ELEMENT_82("minecraft:element_82", 348, "Lead", 0, 2040, 155, 151, 136), +//B_349_ELEMENT_83("minecraft:element_83", 349, "Bismuth", 120, 2040, 155, 150, 135), +//B_350_ELEMENT_84("minecraft:element_84", 350, "Polonium", 240, 2040, 159, 132, 130), +//B_351_ELEMENT_85("minecraft:element_85", 351, "Astatine", 360, 2040, 184, 138, 92), +//B_352_ELEMENT_86("minecraft:element_86", 352, "Radon", 480, 2040, 155, 116, 182), +//B_353_ELEMENT_87("minecraft:element_87", 353, "Francium", 600, 2040, 104, 125, 181), +//B_354_ELEMENT_88("minecraft:element_88", 354, "Radium", 720, 2040, 93, 149, 162), +//B_355_ELEMENT_89("minecraft:element_89", 355, "Actinium", 840, 2040, 114, 89, 156), +//B_356_ELEMENT_90("minecraft:element_90", 356, "Thorium", 960, 2040, 115, 90, 156), +//B_357_ELEMENT_91("minecraft:element_91", 357, "Protactinium", 1080, 2040, 115, 90, 156), +//B_358_ELEMENT_92("minecraft:element_92", 358, "Uranium", 1200, 2040, 111, 84, 154), +//B_359_ELEMENT_93("minecraft:element_93", 359, "Neptunium", 1320, 2040, 117, 93, 157), +//B_360_ELEMENT_94("minecraft:element_94", 360, "Plutonium", 1440, 2040, 114, 89, 156), +//B_361_ELEMENT_95("minecraft:element_95", 361, "Americium", 1560, 2040, 117, 92, 157), +//B_362_ELEMENT_96("minecraft:element_96", 362, "Curium", 1680, 2040, 115, 90, 156), +//B_363_ELEMENT_97("minecraft:element_97", 363, "Berkelium", 1800, 2040, 116, 92, 157), +//B_364_ELEMENT_98("minecraft:element_98", 364, "Californium", 1920, 2040, 114, 88, 156), +//B_365_ELEMENT_99("minecraft:element_99", 365, "Einsteinium", 2040, 2040, 116, 91, 156), +//B_366_ELEMENT_100("minecraft:element_100", 366, "Fermium", 2160, 2040, 116, 92, 157), +//B_367_ELEMENT_101("minecraft:element_101", 367, "Mendelevium", 2280, 2040, 118, 94, 157), +//B_368_ELEMENT_102("minecraft:element_102", 368, "Nobelium", 0, 2160, 116, 91, 157), +//B_369_ELEMENT_103("minecraft:element_103", 369, "Lawrencium", 120, 2160, 114, 88, 156), +//B_370_ELEMENT_104("minecraft:element_104", 370, "Rutherfordium", 240, 2160, 130, 130, 130), +//B_371_ELEMENT_105("minecraft:element_105", 371, "Dubnium", 360, 2160, 131, 131, 131), +//B_372_ELEMENT_106("minecraft:element_106", 372, "Seaborgium", 480, 2160, 131, 131, 131), +//B_373_ELEMENT_107("minecraft:element_107", 373, "Bohrium", 600, 2160, 131, 131, 131), +//B_374_ELEMENT_108("minecraft:element_108", 374, "Hassium", 720, 2160, 130, 130, 130), +//B_375_ELEMENT_109("minecraft:element_109", 375, "Meitnerium", 840, 2160, 130, 130, 130), +//B_376_ELEMENT_110("minecraft:element_110", 376, "Darmstadtium", 960, 2160, 130, 130, 130), +//B_377_ELEMENT_111("minecraft:element_111", 377, "Roentgenium", 1080, 2160, 131, 131, 131), +//B_378_ELEMENT_112("minecraft:element_112", 378, "Copernicium", 1200, 2160, 128, 128, 128), +//B_379_ELEMENT_113("minecraft:element_113", 379, "Nihonium", 1320, 2160, 156, 152, 137), +//B_380_ELEMENT_114("minecraft:element_114", 380, "Flerovium", 1440, 2160, 154, 150, 135), +//B_381_ELEMENT_115("minecraft:element_115", 381, "Moscovium", 1560, 2160, 155, 151, 136), +//B_382_ELEMENT_116("minecraft:element_116", 382, "Livermorium", 1680, 2160, 154, 150, 134), +//B_383_ELEMENT_117("minecraft:element_117", 383, "Tennessine", 1800, 2160, 183, 137, 91), +//B_384_ELEMENT_118("minecraft:element_118", 384, "Oganesson", 1920, 2160, 156, 118, 182), + B_385_SEAGRASS("minecraft:seagrass", 385, "Seagrass", 2040, 2160, 52, 128, 10), + B_386_CORAL("minecraft:coral", 386, "Coral", 2160, 2160, 33, 58, 138), + B_387_CORAL_BLOCK("minecraft:coral_block", 387, "Coral Block", 2280, 2160, 38, 68, 162), + B_388_CORAL_FAN("minecraft:coral_fan", 388, "Coral Fan", 0, 2280, 54, 96, 219), + B_389_CORAL_FAN_DEAD("minecraft:coral_fan_dead", 389, "Dead Coral Fan", 120, 2280, 135, 128, 124), + B_390_CORAL_FAN_HANG("minecraft:coral_fan_hang", 390, "Coral Fan", 240, 2280, 54, 96, 219), + B_391_CORAL_FAN_HANG2("minecraft:coral_fan_hang2", 391, "Coral Fan", 360, 2280, 168, 34, 168), + B_392_CORAL_FAN_HANG3("minecraft:coral_fan_hang3", 392, "Coral Fan", 480, 2280, 219, 195, 66), + B_393_KELP("minecraft:kelp", 393, "Kelp", 600, 2280, 86, 126, 39), + B_394_DRIED_KELP_BLOCK("minecraft:dried_kelp_block", 394, "Dried Kelp Block", 720, 2280, 33, 41, 25), + B_395_ACACIA_BUTTON("minecraft:acacia_button", 395, "Acacia Button", 840, 2280, 138, 74, 41), + B_396_BIRCH_BUTTON("minecraft:birch_button", 396, "Birch Button", 960, 2280, 158, 144, 100), + B_397_DARK_OAK_BUTTON("minecraft:dark_oak_button", 397, "Dark Oak Button", 1080, 2280, 55, 36, 16), + B_398_JUNGLE_BUTTON("minecraft:jungle_button", 398, "Jungle Button", 1200, 2280, 133, 96, 68), + B_399_SPRUCE_BUTTON("minecraft:spruce_button", 399, "Spruce Button", 1320, 2280, 95, 70, 40), + B_400_ACACIA_TRAPDOOR("minecraft:acacia_trapdoor", 400, "Acacia Trapdoor", 1440, 2280, 124, 68, 39), + B_401_BIRCH_TRAPDOOR("minecraft:birch_trapdoor", 401, "Birch Trapdoor", 1560, 2280, 163, 152, 119), + B_402_DARK_OAK_TRAPDOOR("minecraft:dark_oak_trapdoor", 402, "Dark Oak Trapdoor", 1680, 2280, 59, 39, 18), + B_403_JUNGLE_TRAPDOOR("minecraft:jungle_trapdoor", 403, "Jungle Trapdoor", 1800, 2280, 122, 88, 61), + B_404_SPRUCE_TRAPDOOR("minecraft:spruce_trapdoor", 404, "Spruce Trapdoor", 1920, 2280, 93, 70, 42), + B_405_ACACIA_PRESSURE_PLATE("minecraft:acacia_pressure_plate", 405, "Acacia Pressure Plate", 2040, 2280, 154, 82, 46), + B_406_BIRCH_PRESSURE_PLATE("minecraft:birch_pressure_plate", 406, "Birch Pressure Plate", 2160, 2280, 177, 161, 111), + B_407_DARK_OAK_PRESSURE_PLATE("minecraft:dark_oak_pressure_plate", 407, "Dark Oak Pressure Plate", 2280, 2280, 60, 38, 18), + B_408_JUNGLE_PRESSURE_PLATE("minecraft:jungle_pressure_plate", 408, "Jungle Pressure Plate", 0, 2400, 146, 104, 73), + B_409_SPRUCE_PRESSURE_PLATE("minecraft:spruce_pressure_plate", 409, "Spruce Pressure Plate", 120, 2400, 105, 77, 44), + B_410_CARVED_PUMPKIN("minecraft:carved_pumpkin", 410, "Carved Pumpkin", 240, 2400, 140, 82, 17), + B_411_SEA_PICKLE("minecraft:sea_pickle", 411, "Sea Pickle", 360, 2400, 81, 86, 39), + B_412_CONDUIT("minecraft:conduit", 412, "Conduit", 480, 2400, 125, 108, 88), + B_414_TURTLE_EGG("minecraft:turtle_egg", 414, "Sea Turtle Egg", 600, 2400, 172, 173, 149), + B_415_BUBBLE_COLUMN("minecraft:bubble_column", 415, "Bubble Column", 720, 2400, 93, 201, 251), + B_416_BARRIER("minecraft:barrier", 416, "Barrier", 840, 2400, 211, 0, 0), + B_417_STONE_SLAB3("minecraft:stone_slab3", 417, "End Stone Brick Slab", 960, 2400, 180, 184, 133), + B_418_BAMBOO("minecraft:bamboo", 418, "Bamboo", 1080, 2400, 86, 123, 32), + B_419_BAMBOO_SAPLING("minecraft:bamboo_sapling", 419, "Bamboo Sapling", 1200, 2400, 89, 89, 34), + B_420_SCAFFOLDING("minecraft:scaffolding", 420, "Scaffolding", 1320, 2400, 158, 129, 73), + B_421_STONE_SLAB4("minecraft:stone_slab4", 421, "Mossy Stone Brick Slab", 1440, 2400, 96, 100, 89), + B_422_DOUBLE_STONE_SLAB3("minecraft:double_stone_slab3", 422, "Double End Stone Brick Slab", 1560, 2400, 171, 175, 126), + B_423_DOUBLE_STONE_SLAB4("minecraft:double_stone_slab4", 423, "Double Mossy Stone Brick Slab", 1680, 2400, 90, 94, 82), + B_424_GRANITE_STAIRS("minecraft:granite_stairs", 424, "Granite Stairs", 1800, 2400, 120, 83, 69), + B_425_DIORITE_STAIRS("minecraft:diorite_stairs", 425, "Diorite Stairs", 1920, 2400, 153, 153, 154), + B_426_ANDESITE_STAIRS("minecraft:andesite_stairs", 426, "Andesite Stairs", 2040, 2400, 109, 109, 109), + B_427_POLISHED_GRANITE_STAIRS("minecraft:polished_granite_stairs", 427, "Polished Granite Stairs", 2160, 2400, 122, 85, 71), + B_428_POLISHED_DIORITE_STAIRS("minecraft:polished_diorite_stairs", 428, "Polished Diorite Stairs", 2280, 2400, 153, 153, 154), + B_429_POLISHED_ANDESITE_STAIRS("minecraft:polished_andesite_stairs", 429, "Polished Andesite Stairs", 0, 2520, 105, 107, 107), + B_430_MOSSY_STONE_BRICK_STAIRS("minecraft:mossy_stone_brick_stairs", 430, "Mossy Stone Brick Stairs", 120, 2520, 92, 96, 84), + B_431_SMOOTH_RED_SANDSTONE_STAIRS("minecraft:smooth_red_sandstone_stairs", 431, "Smooth Red Sandstone Stairs", 240, 2520, 147, 79, 25), + B_432_SMOOTH_SANDSTONE_STAIRS("minecraft:smooth_sandstone_stairs", 432, "Smooth Sandstone Stairs", 360, 2520, 181, 173, 139), + B_433_END_BRICK_STAIRS("minecraft:end_brick_stairs", 433, "End Stone Brick Stairs", 480, 2520, 174, 178, 129), + B_434_MOSSY_COBBLESTONE_STAIRS("minecraft:mossy_cobblestone_stairs", 434, "Mossy Cobblestone Stairs", 600, 2520, 89, 95, 77), + B_435_NORMAL_STONE_STAIRS("minecraft:normal_stone_stairs", 435, "Stone Stairs", 720, 2520, 100, 100, 100), + B_436_SPRUCE_STANDING_SIGN("minecraft:spruce_standing_sign", 436, "Spruce Standing Sign", 840, 2520, 73, 54, 31), + B_437_SPRUCE_WALL_SIGN("minecraft:spruce_wall_sign", 437, "Spruce Wall Sign", 960, 2520, 80, 60, 35), + B_438_SMOOTH_STONE("minecraft:smooth_stone", 438, "Smooth Stone", 1080, 2520, 123, 123, 123), + B_439_RED_NETHER_BRICK_STAIRS("minecraft:red_nether_brick_stairs", 439, "Red Nether Brick Stairs", 1200, 2520, 56, 5, 7), + B_440_SMOOTH_QUARTZ_STAIRS("minecraft:smooth_quartz_stairs", 440, "Smooth Quartz Stairs", 1320, 2520, 189, 184, 179), + B_441_BIRCH_STANDING_SIGN("minecraft:birch_standing_sign", 441, "Birch Standing Sign", 1440, 2520, 147, 136, 98), + B_442_BIRCH_WALL_SIGN("minecraft:birch_wall_sign", 442, "Birch Wall Sign", 1560, 2520, 149, 137, 93), + B_443_JUNGLE_STANDING_SIGN("minecraft:jungle_standing_sign", 443, "Jungle Standing Sign", 1680, 2520, 110, 80, 53), + B_444_JUNGLE_WALL_SIGN("minecraft:jungle_wall_sign", 444, "Jungle Wall Sign", 1800, 2520, 120, 86, 59), + B_445_ACACIA_STANDING_SIGN("minecraft:acacia_standing_sign", 445, "Acacia Standing Sign", 1920, 2520, 120, 69, 41), + B_446_ACACIA_WALL_SIGN("minecraft:acacia_wall_sign", 446, "Acacia Wall Sign", 2040, 2520, 129, 70, 39), + B_447_DARKOAK_STANDING_SIGN("minecraft:darkoak_standing_sign", 447, "Dark Oak Standing Sign", 2160, 2520, 44, 29, 14), + B_448_DARKOAK_WALL_SIGN("minecraft:darkoak_wall_sign", 448, "Dark Oak Wall Sign", 2280, 2520, 46, 29, 13), + B_449_LECTERN("minecraft:lectern", 449, "Lectern", 0, 2640, 141, 107, 64), + B_450_GRINDSTONE("minecraft:grindstone", 450, "Grindstone", 120, 2640, 96, 92, 87), + B_451_BLAST_FURNACE("minecraft:blast_furnace", 451, "Blast Furnace", 240, 2640, 76, 76, 76), + B_452_STONECUTTER_BLOCK("minecraft:stonecutter_block", 452, "Stonecutter Block", 360, 2640, 104, 96, 89), + B_453_SMOKER("minecraft:smoker", 453, "Smoker", 480, 2640, 71, 64, 55), + B_454_LIT_SMOKER("minecraft:lit_smoker", 454, "Lit Smoker", 600, 2640, 79, 70, 58), + B_455_CARTOGRAPHY_TABLE("minecraft:cartography_table", 455, "Cartography Table", 720, 2640, 58, 44, 30), + B_456_FLETCHING_TABLE("minecraft:fletching_table", 456, "Fletching Table", 840, 2640, 125, 113, 83), + B_457_SMITHING_TABLE("minecraft:smithing_table", 457, "Smithing Table", 960, 2640, 37, 31, 35), + B_458_BARREL("minecraft:barrel", 458, "Barrel", 1080, 2640, 92, 69, 41), + B_459_LOOM("minecraft:loom", 459, "Loom", 1200, 2640, 114, 90, 65), + B_461_BELL("minecraft:bell", 461, "Bell", 1320, 2640, 121, 113, 77), + B_462_SWEET_BERRY_BUSH("minecraft:sweet_berry_bush", 462, "Sweet Berry Bush", 1440, 2640, 47, 55, 36), + B_463_LANTERN("minecraft:lantern", 463, "Lantern", 1560, 2640, 97, 79, 63), + B_464_CAMPFIRE("minecraft:campfire", 464, "Campfire", 1680, 2640, 146, 110, 50), + B_465_LAVA_CAULDRON("minecraft:lava_cauldron", 465, "Lava Cauldron", 1800, 2640, 76, 60, 51), + B_466_JIGSAW("minecraft:jigsaw", 466, "Jigsaw", 1920, 2640, 59, 59, 59), + B_467_WOOD("minecraft:wood", 467, "Wood", 2040, 2640, 97, 76, 45), + B_468_COMPOSTER("minecraft:composter", 468, "Composter", 2160, 2640, 90, 57, 27), + B_469_LIT_BLAST_FURNACE("minecraft:lit_blast_furnace", 469, "Lit Blast Furnace", 2280, 2640, 79, 77, 76), + B_470_LIGHT_BLOCK("minecraft:light_block", 470, "Light Block", 0, 2760, 153, 147, 149), + B_471_WITHER_ROSE("minecraft:wither_rose", 471, "Wither Rose", 120, 2760, 44, 47, 24), + B_472_STICKYPISTONARMCOLLISION("minecraft:stickypistonarmcollision", 472, "Sticky Piston Head", 240, 2760, 101, 107, 73), + B_473_BEE_NEST("minecraft:bee_nest", 473, "Bee Nest", 360, 2760, 152, 118, 60), + B_474_BEEHIVE("minecraft:beehive", 474, "Beehive", 480, 2760, 131, 106, 65), + B_475_HONEY_BLOCK("minecraft:honey_block", 475, "Honey Block", 600, 2760, 197, 136, 32), + B_476_HONEYCOMB_BLOCK("minecraft:honeycomb_block", 476, "Honeycomb Block", 720, 2760, 182, 117, 23), + B_210_ALLOW("minecraft:allow", 210, "Allow", 840, 2760, 106, 90, 66), + B_211_DENY("minecraft:deny", 211, "Deny", 960, 2760, 87, 87, 87), + B_212_BORDER("minecraft:border", 212, "Border", 1080, 2760, 125, 36, 29), + B_230_CHALKBOARD("minecraft:chalkboard", 230, "Chalkboard", 1200, 2760, 71, 69, 57); +//B_242_CAMERA("minecraft:camera", 242, "", 1320, 2760, 63, 51, 34), + + + private static int SIZE = 120; + + private static WeakReference iconsSheet = new WeakReference<>(null); + + private String identifier; + + private String name; + + private int legacy_id; + + private int iconX; + + private int iconY; + + private int color; + + //@Nullable + private WeakReference icon; + + ListingBlock(String identifier, int legacy_id, String name, int iconX, int iconY, int r, int g, int b) { + this.identifier = identifier; + this.legacy_id = legacy_id; + this.name = name; + this.iconX = iconX; + this.iconY = iconY; + if (r < 0) + color = Color.TRANSPARENT; + else + color = Color.rgb(r, g, b); + icon = new WeakReference<>(null); + } + + public String getIdentifier() { + return identifier; + } + + public int getColor() { + return color; + } + + public int getLegacy_id() { + return legacy_id; + } + + public String getName() { + return name; + } + + public Bitmap getIcon(AssetManager assMan) { + Bitmap icon = this.icon.get(); + if (icon == null) { + if (iconX >= 0) { + Bitmap sheet = iconsSheet.get(); + try { + if (sheet == null) { + sheet = BitmapFactory.decodeStream(assMan.open("block_icons.png")); + iconsSheet = new WeakReference<>(sheet); + } + icon = Bitmap.createBitmap(sheet, iconX, iconY, SIZE, SIZE); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (icon == null) + icon = Bitmap.createBitmap(SIZE, SIZE, Bitmap.Config.ARGB_8888); + this.icon = new WeakReference<>(icon); + } + return icon; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlock.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlock.java new file mode 100644 index 00000000..a95e0c57 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlock.java @@ -0,0 +1,93 @@ +package com.mithrilmania.blocktopograph.block; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; + +import java.io.Serializable; +import java.util.ArrayList; + +public class OldBlock implements Serializable { + + @NonNull + private OldBlockType oldBlockType; + + @NonNull + private KnownBlockRepr legacyBlock; + + private ListingBlock listingBlock; + + @NonNull + private CompoundTag states; + + private int version; + + OldBlock(@NonNull OldBlockType oldBlockType, @NonNull CompoundTag states, int version) { + this.oldBlockType = oldBlockType; + this.states = states; + this.version = version; + KnownBlockRepr legacyBlock = BlockWithStatesToLegacyBlockMapper.getBestRepr(this); + if (legacyBlock == null) { + for (ListingBlock lb : ListingBlock.values()) { + if (lb.getIdentifier().equals(oldBlockType.getName())) { + listingBlock = lb; + break; + } + } + legacyBlock = KnownBlockRepr.guessBlockNew(oldBlockType.getName()); + } + this.legacyBlock = legacyBlock; + } + + OldBlock(@NonNull OldBlockType oldBlockType, @NonNull KnownBlockRepr legacyBlock, int version) { + this.oldBlockType = oldBlockType; + this.states = new CompoundTag("states", new ArrayList<>()); + this.version = version; + this.legacyBlock = legacyBlock; + } + + @NonNull + public String getBlockType() { + return oldBlockType.getName(); + } + + public int getVersion() { + return version; + } + + public boolean isOfSameType(OldBlock oldBlock) { + return oldBlockType == oldBlock.oldBlockType; + } + + public Tag getState(String key) { + return states.getChildTagByKey(key); + } + + @NonNull + public KnownBlockRepr getLegacyBlock() { + return legacyBlock; + } + + public int getColor() { + if (listingBlock != null) + return listingBlock.getColor(); + return legacyBlock.color; + } + + @NonNull + public CompoundTag getStates() { + return states; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (!(obj instanceof OldBlock)) return false; + OldBlock another = (OldBlock) obj; + // Ref compare. + if (oldBlockType != another.oldBlockType) return false; + return states.equals(another.states); + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlockRegistry.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlockRegistry.java new file mode 100644 index 00000000..38e79a3c --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlockRegistry.java @@ -0,0 +1,52 @@ +package com.mithrilmania.blocktopograph.block; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Map; + +public class OldBlockRegistry { + + private int limitedTypes; + private Map blockTypes; + + public OldBlockRegistry() { + blockTypes = new Hashtable<>(1024); + } + + public OldBlockRegistry(int limitedTypes) { + this(); + this.limitedTypes = limitedTypes; + } + + @NonNull + private OldBlockType getBlockType(String name) { + OldBlockType ret = blockTypes.get(name); + if (ret == null) { + ret = new OldBlockType(name); + if (limitedTypes > 0 && blockTypes.size() >= limitedTypes) + throw new RuntimeException("Block types exceeds your set limit."); + blockTypes.put(name, ret); + } + return ret; + } + + @NonNull + public OldBlock createBlock(@NonNull String name, @NonNull CompoundTag states, int version) { + return new OldBlock(getBlockType(name), states, version); + } + + @NonNull + public OldBlock createBlock(@NonNull String name) { + return new OldBlock(getBlockType(name), new CompoundTag("states", new ArrayList<>()), 3841); + } + + @NonNull + public OldBlock createBlock(@NonNull KnownBlockRepr legacyBlock) { + return new OldBlock(getBlockType(legacyBlock.identifier), legacyBlock, 1); + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlockType.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlockType.java new file mode 100644 index 00000000..6ab2d1b0 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/OldBlockType.java @@ -0,0 +1,16 @@ +package com.mithrilmania.blocktopograph.block; + +import java.io.Serializable; + +public class OldBlockType implements Serializable { + + private final String name; + + public OldBlockType(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/BitValuesRange.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/BitValuesRange.java new file mode 100644 index 00000000..6da14fa7 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/BitValuesRange.java @@ -0,0 +1,4 @@ +package com.mithrilmania.blocktopograph.block.blockproperty; + +public class BitValuesRange extends ValuesRange { +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/BlockProperty.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/BlockProperty.java new file mode 100644 index 00000000..be27b3ae --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/BlockProperty.java @@ -0,0 +1,134 @@ +package com.mithrilmania.blocktopograph.block.blockproperty; + +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; + +import java.util.HashMap; +import java.util.Map; + +public enum BlockProperty { + AGE_BIT("age_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + ALLOW_UNDERWATER_BIT("allow_underwater_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + ATTACHED_BIT("attached_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + BREWING_STAND_SLOT_A_BIT("brewing_stand_slot_a_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + BREWING_STAND_SLOT_B_BIT("brewing_stand_slot_b_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + BREWING_STAND_SLOT_C_BIT("brewing_stand_slot_c_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + BUTTON_PRESSED_BIT("button_pressed_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + CONDITIONAL_BIT("conditional_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + CORAL_HANG_TYPE_BIT("coral_hang_type_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + COVERED_BIT("covered_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + DEAD_BIT("dead_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + DISARMED_BIT("disarmed_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + DOOR_HINGE_BIT("door_hinge_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + END_PORTAL_EYE_BIT("end_portal_eye_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + EXPLODE_BIT("explode_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + HEAD_PIECE_BIT("head_piece_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + IN_WALL_BIT("in_wall_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + INFINIBURN_BIT("infiniburn_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + ITEM_FRAME_MAP_BIT("item_frame_map_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + NO_DROP_BIT("no_drop_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + OCCUPIED_BIT("occupied_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + OPEN_BIT("open_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + OUTPUT_LIT_BIT("output_lit_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + OUTPUT_SUBTRACT_BIT("output_subtract_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + PERSISTENT_BIT("persistent_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + POWERED_BIT("powered_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + RAIL_DATA_BIT("rail_data_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + SUSPENDED_BIT("suspended_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + TOGGLE_BIT("toggle_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + TOP_SLOT_BIT("top_slot_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + TRIGGERED_BIT("triggered_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + UPDATE_BIT("update_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + UPPER_BLOCK_BIT("upper_block_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + UPSIDE_DOWN_BIT("upside_down_bit", NBTConstants.NBTType.BYTE, new BitValuesRange()), + AGE("age", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + BITE_COUNTER("bite_counter", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + CLUSTER_COUNT("cluster_count", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1, 2, 3})), + CORAL_DIRECTION("coral_direction", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1, 2, 3})), + CORAL_FAN_DIRECTION("coral_fan_direction", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1})), + DEPRECATED("deprecated", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + DIRECTION("direction", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1, 2, 3})), + FACING_DIRECTION("facing_direction", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1, 2, 3, 4, 5})), + FILL_LEVEL("fill_level", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + GROUND_SIGN_DIRECTION("ground_sign_direction", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + GROWTH("growth", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + HEIGHT("height", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + HUGE_MUSHROOM_BITS("huge_mushroom_bits", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + KELP_AGE("kelp_age", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9})), + LIQUID_DEPTH("liquid_depth", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + MOISTURIZED_AMOUNT("moisturized_amount", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + RAIL_DIRECTION("rail_direction", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + REDSTONE_SIGNAL("redstone_signal", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9})), + REPEATER_DELAY("repeater_delay", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + VINE_DIRECTION_BITS("vine_direction_bits", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0})), + WEIRDO_DIRECTION("weirdo_direction", NBTConstants.NBTType.INT, new EnumValuesRange(new Integer[]{0, 1, 2, 3})), + CAULDRON_LIQUID("cauldron_liquid", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"water"})), + CHEMISTRY_TABLE_TYPE("chemistry_table_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"compound_creator", "element_constructor", "lab_table", "material_reducer"})), + CHISEL_TYPE("chisel_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"chiseled", "default", "lines", "smooth"})), + COLOR("color", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"black", "blue", "brown", "cyan", "gray", "green", "light_blue", "lime", "magenta", "orange", "pink", "purple", "red", "silver", "white", "yellow"})), + CORAL_COLOR("coral_color", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"blue", "pink", "purple", "red", "yellow"})), + DAMAGE("damage", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"slightly_damaged", "undamaged", "very_damaged"})), + DIRT_TYPE("dirt_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"normal"})), + DOUBLE_PLANT_TYPE("double_plant_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"fern", "grass", "paeonia", "rose", "sunflower", "syringa"})), + FLOWER_TYPE("flower_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"allium", "houstonia", "orchid", "oxeye", "poppy", "tulip_orange", "tulip_pink", "tulip_red", "tulip_white"})), + LEVER_DIRECTION("lever_direction", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"down_east_west"})), + MONSTER_EGG_STONE_TYPE("monster_egg_stone_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"chiseled_stone_brick", "cobblestone", "cracked_stone_brick", "mossy_stone_brick", "stone", "stone_brick"})), + NEW_LEAF_TYPE("new_leaf_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"acacia", "dark_oak"})), + NEW_LOG_TYPE("new_log_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"acacia", "dark_oak"})), + OLD_LEAF_TYPE("old_leaf_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"birch", "jungle", "oak", "spruce"})), + OLD_LOG_TYPE("old_log_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"birch", "jungle", "oak", "spruce"})), + PILLAR_AXIS("pillar_axis", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"x", "y", "z"})), + PORTAL_AXIS("portal_axis", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"unknown"})), + PRISMARINE_BLOCK_TYPE("prismarine_block_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"bricks", "dark", "default"})), + SAND_STONE_TYPE("sand_stone_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"cut", "default", "heiroglyphs"})), + SAND_TYPE("sand_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"normal", "red"})), + SAPLING_TYPE("sapling_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"acacia", "birch", "dark_oak", "jungle", "oak", "spruce"})), + SEA_GRASS_TYPE("sea_grass_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"default", "double_bot", "double_top"})), + SPONGE_TYPE("sponge_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"dry", "wet"})), + STONE_BRICK_TYPE("stone_brick_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"chiseled", "cracked", "default", "mossy", "smooth"})), + STONE_SLAB_TYPE("stone_slab_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"brick", "cobblestone", "nether_brick", "quartz", "sandstone", "smooth_stone", "stone_brick", "wood"})), + STONE_SLAB_TYPE_2("stone_slab_type_2", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"purpur", "red_sandstone"})), + STONE_TYPE("stone_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"andesite", "andesite_smooth", "diorite", "diorite_smooth", "granite", "granite_smooth", "stone"})), + STRUCTURE_BLOCK_TYPE("structure_block_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"corner", "data", "export", "invalid", "load", "save"})), + TALL_GRASS_TYPE("tall_grass_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"fern", "tall"})), + TORCH_FACING_DIRECTION("torch_facing_direction", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"east", "north", "south", "top", "unknown", "west"})), + WALL_BLOCK_TYPE("wall_block_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"cobblestone", "mossy_cobblestone"})), + WOOD_TYPE("wood_type", NBTConstants.NBTType.STRING, new EnumValuesRange(new String[]{"acacia", "birch", "dark_oak", "jungle", "oak", "spruce"})); + + + private static final Map blockProperties = new HashMap<>(); + + private final String name; + + private final NBTConstants.NBTType type; + + private final ValuesRange valuesRange; + + static { + for (var property : BlockProperty.values()) blockProperties.put(property.name, property); + } + + BlockProperty(String name, NBTConstants.NBTType type, ValuesRange valuesRange) { + this.name = name; + this.type = type; + this.valuesRange = valuesRange; + } + + @Nullable + public static BlockProperty get(String name){ + return blockProperties.get(name); + } + + public String getName() { + return name; + } + + public NBTConstants.NBTType getType() { + return type; + } + + public ValuesRange getValuesRange() { + return valuesRange; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/EnumValuesRange.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/EnumValuesRange.java new file mode 100644 index 00000000..a12171ae --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/EnumValuesRange.java @@ -0,0 +1,16 @@ +package com.mithrilmania.blocktopograph.block.blockproperty; + +import com.mithrilmania.blocktopograph.nbt.tags.Tag; + +public class EnumValuesRange extends ValuesRange { + + private final Object[] values; + + public EnumValuesRange(Object[] values) { + this.values = values; + } + + public Object[] getValues() { + return values; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/ValuesRange.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/ValuesRange.java new file mode 100644 index 00000000..dd67e8ca --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/blockproperty/ValuesRange.java @@ -0,0 +1,4 @@ +package com.mithrilmania.blocktopograph.block.blockproperty; + +public abstract class ValuesRange { +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/BlockIcon.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/BlockIcon.java new file mode 100644 index 00000000..3500921b --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/BlockIcon.java @@ -0,0 +1,11 @@ +package com.mithrilmania.blocktopograph.block.icon; + +import android.content.Context; +import android.graphics.Bitmap; + +import java.io.Serializable; + +public abstract class BlockIcon implements Serializable{ + + abstract public Bitmap getIcon(Context context); +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/NoBlockIcon.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/NoBlockIcon.java new file mode 100644 index 00000000..8fff5dac --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/NoBlockIcon.java @@ -0,0 +1,11 @@ +package com.mithrilmania.blocktopograph.block.icon; + +import android.content.Context; +import android.graphics.Bitmap; + +public class NoBlockIcon extends BlockIcon{ + + public Bitmap getIcon(Context context){ + return null; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/TexPathBlockIcon.java b/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/TexPathBlockIcon.java new file mode 100644 index 00000000..55145b86 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/block/icon/TexPathBlockIcon.java @@ -0,0 +1,45 @@ +package com.mithrilmania.blocktopograph.block.icon; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; + +import java.io.FileNotFoundException; +import java.lang.ref.WeakReference; + +public class TexPathBlockIcon extends BlockIcon { + + private final String texPath; + + private transient WeakReference texture; + + public TexPathBlockIcon(String texPath) { + this.texPath = texPath; + texture = null; + } + + public Bitmap getIcon(Context context) { + var result = texture == null ? null : texture.get(); + if (result == null) { + result = loadIcon(context); + if (result != null) texture = new WeakReference<>(result); + } + return result; + } + + private Bitmap loadIcon(Context context) { + try { + return Bitmap.createScaledBitmap( + BitmapFactory.decodeStream( + context.getAssets().open(texPath)), 120, 120, false); + } catch (FileNotFoundException e) { + //TODO file-paths were generated from block names; some do not actually exist... + } catch (Exception e) { + Log.d(KnownBlockRepr.class, e); + } + return null; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/BedrockChunk.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/BedrockChunk.java new file mode 100644 index 00000000..c98dd4a4 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/BedrockChunk.java @@ -0,0 +1,302 @@ +package com.mithrilmania.blocktopograph.chunk; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.BuildConfig; +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.Block; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.chunk.terrain.TerrainSubChunk; +import com.mithrilmania.blocktopograph.map.Biome; +import com.mithrilmania.blocktopograph.map.Dimension; +import com.mithrilmania.blocktopograph.util.ColorUtil; +import com.mithrilmania.blocktopograph.util.Noise; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public final class BedrockChunk extends Chunk { + + private static final int POS_HEIGHTMAP = 0; + private static final int POS_BIOME_DATA = 0x200; + public static final int DATA2D_LENGTH = 0x300; + + private boolean mHasBlockLight; + private final boolean[] mDirtyList; + private final boolean[] mVoidList; + private final boolean[] mErrorList; + private boolean mIs2dDirty; + private final TerrainSubChunk[] mTerrainSubChunks; + private volatile ByteBuffer data2D; + + BedrockChunk(WorldData worldData, Version version, int chunkX, int chunkZ, Dimension dimension, + boolean createIfMissing) { + super(worldData, version, chunkX, chunkZ, dimension); + mVoidList = new boolean[16]; + mErrorList = new boolean[16]; + mDirtyList = new boolean[16]; + mTerrainSubChunks = new TerrainSubChunk[16]; + load2dData(createIfMissing); + mHasBlockLight = true; + mIs2dDirty = false; + } + + private void load2dData(boolean createIfMissing) { + if (data2D == null) { + try { + byte[] rawData = mWorldData.get().getChunkData( + mChunkX, mChunkZ, ChunkTag.DATA_2D, mDimension, (byte) 0, false); + if (rawData == null) { + if (createIfMissing) { + this.data2D = ByteBuffer.allocate(DATA2D_LENGTH); + } else { + mIsError = true; + mIsVoid = true; + } + return; + } + this.data2D = ByteBuffer.wrap(rawData); + } catch (Exception e) { + if (BuildConfig.DEBUG) { + Log.d(this, e); + } + mIsError = true; + mIsVoid = true; + } + } + } + + @Nullable + private TerrainSubChunk getSubChunk(int which, boolean createIfMissing) { + if (mIsError || mVoidList[which]) return null; + TerrainSubChunk ret = mTerrainSubChunks[which]; + if (ret == null) { + byte[] raw; + WorldData worldData = mWorldData.get(); + try { + raw = worldData.getChunkData(mChunkX, mChunkZ, + ChunkTag.TERRAIN, mDimension, (byte) which, true); + if (raw == null && !createIfMissing) { + mVoidList[which] = true; + return null; + } + } catch (Exception e) { + if (BuildConfig.DEBUG) { + Log.d(this, e); + } + mErrorList[which] = true; + mVoidList[which] = true; + return null; + } + ret = raw == null ? + TerrainSubChunk.createEmpty(8) : + TerrainSubChunk.create(raw); + if (ret == null || ret.isError()) { + mVoidList[which] = true; + mErrorList[which] = true; + ret = null; + } else if (!ret.hasBlockLight()) mHasBlockLight = false; + mTerrainSubChunks[which] = ret; + } + return ret; + } + + private int get2dOffset(int x, int z) { + return (z << 4) | x; + } + + @Override + public boolean supportsBlockLightValues() { + return mHasBlockLight; + } + + @Override + public boolean supportsHeightMap() { + return true; + } + + @Override + public int getHeightLimit() { + return 256; + } + + @Override + public int getHeightMapValue(int x, int z) { + if (mIsVoid) return 0; + short h = data2D.getShort(POS_HEIGHTMAP + (get2dOffset(x, z) << 1)); + return ((h & 0xff) << 8) | ((h >> 8) & 0xff); + } + + private void setHeightMapValue(int x, int z, short height) { + if (mIsVoid) return; + data2D.putShort(POS_HEIGHTMAP + (get2dOffset(x, z) << 1), Short.reverseBytes(height)); + } + + @Override + public int getBiome(int x, int z) { + if (mIsVoid) return 0; + return data2D.get(POS_BIOME_DATA + get2dOffset(x, z)); + } + + @Override + public void setBiome(int x, int z, int id) { + if (mIsVoid) return; + data2D.put(POS_BIOME_DATA + get2dOffset(x, z), (byte) id); + mIs2dDirty = true; + } + + private int getNoise(int x, int z) { + // noise values are between -1 and 1 + // 0.0001 is added to the coordinates because integer values result in 0 + double xval = (mChunkX << 4) | x; + double zval = (mChunkZ << 4) | z; + double oct1 = Noise.noise( + (xval / 100.0) % 256 + 0.0001, + (zval / 100.0) % 256 + 0.0001); + double oct2 = Noise.noise( + (xval / 20.0) % 256 + 0.0001, + (zval / 20.0) % 256 + 0.0001); + double oct3 = Noise.noise( + (xval / 3.0) % 256 + 0.0001, + (zval / 3.0) % 256 + 0.0001); + return (int) (60 + (40 * oct1) + (14 * oct2) + (6 * oct3)); + } + + @Override + public int getGrassColor(int x, int z) { + Biome biome = Biome.getBiome(getBiome(x, z) & 0xff); + int noise = getNoise(x, z); + int r = 30 + (biome.color.red / 5) + noise; + int g = 110 + (biome.color.green / 5) + noise; + int b = 30 + (biome.color.blue / 5) + noise; + return ColorUtil.truncateRgb(r, g, b); + } + + @NonNull + @Override + public BlockTemplate getBlockTemplate(int x, int y, int z, int layer) { + if (x >= 16 || y >= 256 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return BlockTemplates.getAirTemplate(); + TerrainSubChunk subChunk = getSubChunk(y >> 4, false); + if (subChunk == null) + return BlockTemplates.getAirTemplate(); + return subChunk.getBlockTemplate(x, y & 0xf, z, layer); + } + + @NonNull + @Override + public Block getBlock(int x, int y, int z, int layer) { + if (x >= 16 || y >= 256 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + throw new IllegalArgumentException(); + TerrainSubChunk subChunk = getSubChunk(y >> 4, false); + if (subChunk == null) + return BlockTemplates.getAirTemplate().getBlock(); + return subChunk.getBlock(x, y & 0xf, z, layer); + } + + @Override + public void setBlock(int x, int y, int z, int layer, @NonNull Block block) { + if (x >= 16 || y >= 256 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return; + int which = y >> 4; + TerrainSubChunk subChunk = getSubChunk(which, true); + if (subChunk == null) return; + subChunk.setBlock(x, y & 0xf, z, layer, block); + mDirtyList[which] = true; + BlockTemplate template = BlockTemplates.getBest(block); + // Height increased. + if (template != BlockTemplates.getAirTemplate() && getHeightMapValue(x, z) < y) { + mIs2dDirty = true; + setHeightMapValue(x, z, (short) (y + 1)); + // Roof removed. + } else if (template == BlockTemplates.getAirTemplate() && getHeightMapValue(x, z) == y) { + mIs2dDirty = true; + int height = 0; + for (int h = y - 1; h >= 0; h--) { + if (getBlockTemplate(x, h, z) != BlockTemplates.getAirTemplate()) { + height = h + 1; + break; + } + } + setHeightMapValue(x, z, (short) height); + } + } + + @Override + public int getBlockLightValue(int x, int y, int z) { + if (!mHasBlockLight || x >= 16 || y >= 256 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return 0; + TerrainSubChunk subChunk = getSubChunk(y >> 4, false); + if (subChunk == null) return 0; + return subChunk.getBlockLightValue(x, y & 0xf, z); + } + + @Override + public int getSkyLightValue(int x, int y, int z) { + if (x >= 16 || y >= 256 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return 0; + TerrainSubChunk subChunk = getSubChunk(y >> 4, false); + if (subChunk == null) return 0; + return subChunk.getSkyLightValue(x, y & 0xf, z); + } + + @Override + public int getHighestBlockYUnderAt(int x, int z, int y) { + if (x >= 16 || y >= 256 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return -1; + TerrainSubChunk subChunk; + for (int which = y >> 4; which >= 0; which--) { + subChunk = getSubChunk(which, false); + if (subChunk == null) continue; + for (int innerY = (which == (y >> 4)) ? y & 0xf : 15; innerY >= 0; innerY--) { + if (subChunk.getBlockTemplate(x, innerY, z, 0) != BlockTemplates.getAirTemplate()) + return (which << 4) | innerY; + } + } + return -1; + } + + @Override + public int getCaveYUnderAt(int x, int z, int y) { + if (x >= 16 || y >= 256 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return -1; + TerrainSubChunk subChunk; + for (int which = y >> 4; which >= 0; which--) { + subChunk = getSubChunk(which, false); + if (subChunk == null) continue; + for (int innerY = (which == (y >> 4)) ? y & 0xf : 15; innerY >= 0; innerY--) { + if (subChunk.getBlockTemplate(x, innerY, z, 0) == BlockTemplates.getAirTemplate()) + return (which << 4) | innerY; + } + } + return -1; + } + + @Override + public void save() throws WorldData.WorldDBException, IOException { + + if (mIsError || mIsVoid) return; + + WorldData worldData = mWorldData.get(); + if (worldData == null) + throw new RuntimeException("World data is null."); + + // Save biome and hightmap. + if (mIs2dDirty) + worldData.writeChunkData( + mChunkX, mChunkZ, ChunkTag.DATA_2D, mDimension, (byte) 0, false, data2D.array()); + + // Save subChunks. + for (int i = 0, mTerrainSubChunksLength = mTerrainSubChunks.length; i < mTerrainSubChunksLength; i++) { + TerrainSubChunk subChunk = mTerrainSubChunks[i]; + if (subChunk == null || mVoidList[i] || !mDirtyList[i]) continue; + //Log.d(this,"Saving "+i); + subChunk.save(worldData, mChunkX, mChunkZ, mDimension, i); + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Chunk.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Chunk.java index e473b1d5..fc888daa 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Chunk.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Chunk.java @@ -1,122 +1,172 @@ package com.mithrilmania.blocktopograph.chunk; +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.Log; import com.mithrilmania.blocktopograph.WorldData; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; +import com.mithrilmania.blocktopograph.block.Block; +import com.mithrilmania.blocktopograph.block.BlockTemplate; import com.mithrilmania.blocktopograph.map.Dimension; -import java.util.concurrent.atomic.AtomicReferenceArray; +import java.io.IOException; +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.stream.IntStream; + +public abstract class Chunk { + + protected final WeakReference mWorldData; + protected final Version mVersion; + public final int mChunkX; + public final int mChunkZ; + public final Dimension mDimension; + protected NBTChunkData mEntity; + protected NBTChunkData mTileEntity; + boolean mIsVoid; + boolean mIsError; + + Chunk(WorldData worldData, Version version, int chunkX, int chunkZ, Dimension dimension) { + mWorldData = new WeakReference<>(worldData); + mVersion = version; + mChunkX = chunkX; + mChunkZ = chunkZ; + mDimension = dimension; + mIsVoid = false; + mIsError = false; + try { + mEntity = version.createEntityChunkData(this); + mTileEntity = version.createBlockEntityChunkData(this); + } catch (Version.VersionException e) { + Log.d(this, e); + } + } + public static Chunk createEmpty(@NonNull WorldData worldData, int chunkX, int chunkZ, Dimension dimension, + Version createOfVersion) { + Chunk chunk; + switch (createOfVersion) { + case V1_2_PLUS: + case V1_16_PLUS: + try { + worldData.writeChunkData(chunkX, chunkZ, ChunkTag.GENERATOR_STAGE, dimension, (byte) 0, false, new byte[]{2, 0, 0, 0}); + worldData.writeChunkData(chunkX, chunkZ, ChunkTag.VERSION_PRE16, dimension, (byte) 0, false, new byte[]{0xf}); + chunk = new BedrockChunk(worldData, createOfVersion, chunkX, chunkZ, dimension, true); + } catch (Exception e) { + Log.d(Chunk.class, e); + chunk = new VoidChunk(worldData, createOfVersion, chunkX, chunkZ, dimension); + } + break; + default: + chunk = new VoidChunk(worldData, createOfVersion, chunkX, chunkZ, dimension); + } + return chunk; + } -public class Chunk { + public static Chunk create(@NonNull WorldData worldData, int chunkX, int chunkZ, Dimension dimension, + boolean createIfMissing, Version createOfVersion) { + Version version; + try { + byte[] data = worldData.getChunkData(chunkX, chunkZ, ChunkTag.VERSION_PRE16, dimension); + if (data == null) + data = worldData.getChunkData(chunkX, chunkZ, ChunkTag.VERSION, dimension); + if (data == null && createIfMissing) + return createEmpty(worldData, chunkX, chunkZ, dimension, createOfVersion); + version = Version.getVersion(data); + } catch (WorldData.WorldDBLoadException | WorldData.WorldDBException e) { + Log.d(Chunk.class, e); + version = Version.ERROR; + } + Chunk chunk; + switch (version) { +// case ERROR: +// case OLD_LIMITED: +// chunk = new VoidChunk(worldData, version, chunkX, chunkZ, dimension); +// chunk.mIsError = true; +// break; +// case v0_9: +// chunk = new PocketChunk(worldData, version, chunkX, chunkZ, dimension); +// break; +// case V1_0: +// case V1_1: + case V1_2_PLUS: + case V1_16_PLUS: + chunk = new BedrockChunk(worldData, version, chunkX, chunkZ, dimension, false); + break; + case NULL: + default: + chunk = new VoidChunk(worldData, version, chunkX, chunkZ, dimension); + } + return chunk; + } - public final WorldData worldData; + public final WorldData getWorldData() { + return mWorldData.get(); + } - public final int x, z; - public final Dimension dimension; + public final boolean isVoid() { + return mIsVoid; + } - private Version version; + public final boolean isError() { + return mIsError; + } - private AtomicReferenceArray - terrain = new AtomicReferenceArray<>(256); + abstract public boolean supportsBlockLightValues(); - private volatile NBTChunkData entity, blockEntity; + abstract public boolean supportsHeightMap(); - public Chunk(WorldData worldData, int x, int z, Dimension dimension) { - this.worldData = worldData; - this.x = x; - this.z = z; - this.dimension = dimension; - } + abstract public int getHeightLimit(); - public TerrainChunkData getTerrain(byte subChunk) throws Version.VersionException { - TerrainChunkData data = terrain.get(subChunk & 0xff); - if(data == null){ - data = this.getVersion().createTerrainChunkData(this, subChunk); - terrain.set(subChunk & 0xff, data); - } - return data; - } + abstract public int getHeightMapValue(int x, int z); - public NBTChunkData getEntity() throws Version.VersionException { - if(entity == null) entity = this.getVersion().createEntityChunkData(this); - return entity; - } + abstract public int getBiome(int x, int z); + + abstract public void setBiome(int x, int z, int id); + abstract public int getGrassColor(int x, int z); - public NBTChunkData getBlockEntity() throws Version.VersionException { - if(blockEntity == null) blockEntity = this.getVersion().createBlockEntityChunkData(this); - return blockEntity; + @NonNull + public BlockTemplate getBlockTemplate(int x, int y, int z) { + return getBlockTemplate(x, y, z, 0); } - public Version getVersion(){ - if(this.version == null) try { - byte[] data = this.worldData.getChunkData(x, z, ChunkTag.VERSION, dimension, (byte) 0, false); - this.version = Version.getVersion(data); - } catch (WorldData.WorldDBLoadException | WorldData.WorldDBException e) { - e.printStackTrace(); - this.version = Version.ERROR; - } + @NonNull + abstract public BlockTemplate getBlockTemplate(int x, int y, int z, int layer); - return this.version; + @NonNull + public Block getBlock(int x, int y, int z) { + return getBlock(x, y, z, 0); } + @NonNull + abstract public Block getBlock(int x, int y, int z, int layer); - //TODO: should we use the heightmap??? - public int getHighestBlockYAt(int x, int z) throws Version.VersionException { - Version cVersion = getVersion(); - TerrainChunkData data; - for(int subChunk = cVersion.subChunks - 1; subChunk >= 0; subChunk--) { - data = this.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()) continue; + abstract public void setBlock(int x, int y, int z, int layer, @NonNull Block block); - for (int y = cVersion.subChunkHeight; y >= 0; y--) { - if (data.getBlockTypeId(x & 15, y, z & 15) != 0) - return (subChunk * cVersion.subChunkHeight) + y; - } - } - return -1; - } + abstract public int getBlockLightValue(int x, int y, int z); - public int getHighestBlockYUnderAt(int x, int z, int y) throws Version.VersionException { - Version cVersion = getVersion(); - int offset = y % cVersion.subChunkHeight; - int subChunk = y / cVersion.subChunkHeight; - TerrainChunkData data; + abstract public int getSkyLightValue(int x, int y, int z); - for(; subChunk >= 0; subChunk--) { - data = this.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()) continue; + abstract public int getHighestBlockYUnderAt(int x, int z, int y); - for (y = offset; y >= 0; y--) { - if (data.getBlockTypeId(x & 15, y, z & 15) != 0) - return (subChunk * cVersion.subChunkHeight) + y; - } + abstract public int getCaveYUnderAt(int x, int z, int y); - //start at the top of the next chunk! (current offset might differ) - offset = cVersion.subChunkHeight - 1; - } - return -1; - } + abstract public void save() throws WorldData.WorldDBException, IOException; - public int getCaveYUnderAt(int x, int z, int y) throws Version.VersionException { - Version cVersion = getVersion(); - int offset = y % cVersion.subChunkHeight; - int subChunk = y / cVersion.subChunkHeight; - TerrainChunkData data; - - for(; subChunk >= 0; subChunk--) { - data = this.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()) continue; - for (y = offset; y >= 0; y--) { - if (data.getBlockTypeId(x & 15, y, z & 15) == 0) - return (subChunk * cVersion.subChunkHeight) + y; - } - - //start at the top of the next chunk! (current offset might differ) - offset = cVersion.subChunkHeight - 1; - } - return -1; + public void deleteThis() throws Exception { + // TODO: delete all with given prefix + WorldData worldData = mWorldData.get(); + if (worldData == null) throw new RuntimeException("World data is null."); + worldData.removeFullChunk(mChunkX, mChunkZ, mDimension); + // Prevent saving. + mIsError = true; } + public final NBTChunkData getEntity() { + return mEntity; + } + public final NBTChunkData getBlockEntity() { + return mTileEntity; + } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkData.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkData.java index f0f496f3..01ed759a 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkData.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkData.java @@ -4,15 +4,15 @@ import com.mithrilmania.blocktopograph.WorldData; import java.io.IOException; +import java.lang.ref.WeakReference; public abstract class ChunkData { - public final Chunk chunk; + public final WeakReference chunk; - - public ChunkData(Chunk chunk){ - this.chunk = chunk; + public ChunkData(Chunk chunk) { + this.chunk = new WeakReference<>(chunk); } public abstract void createEmpty(); diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkManager.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkManager.java index fbdf8a06..82f12d61 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkManager.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkManager.java @@ -1,49 +1,5 @@ package com.mithrilmania.blocktopograph.chunk; -import android.annotation.SuppressLint; - -import com.mithrilmania.blocktopograph.WorldData; -import com.mithrilmania.blocktopograph.chunk.terrain.V0_9_TerrainChunkData; -import com.mithrilmania.blocktopograph.map.Dimension; - -import java.util.HashMap; -import java.util.Map; - - public class ChunkManager { - @SuppressLint("UseSparseArrays") - private Map chunks = new HashMap<>(); - - private WorldData worldData; - - public final Dimension dimension; - - public ChunkManager(WorldData worldData, Dimension dimension){ - this.worldData = worldData; - this.dimension = dimension; - } - - - public static long xzToKey(int x, int z){ - return (((long) x) << 32) | (((long) z) & 0xFFFFFFFFL); - } - - public Chunk getChunk(int cX, int cZ) { - long key = xzToKey(cX, cZ); - Chunk chunk = chunks.get(key); - if(chunk == null) { - chunk = new Chunk(worldData, cX, cZ, dimension); - this.chunks.put(key, chunk); - } - return chunk; - } - - public void disposeAll(){ - this.chunks.clear(); - } - - - - } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkTag.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkTag.java index 50344d49..be7ab281 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkTag.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/ChunkTag.java @@ -2,7 +2,7 @@ /** * Reference from Tommaso Checchi (/u/mojang_tommo), MCPE developer: - * https://www.reddit.com/r/MCPE/comments/5cw2tm/level_format_changes_in_mcpe_0171_100/d9zv9s8/ + * https://www.reddit.com/r/MCPE/comments/5cw2tm/level_format_changes_in_mcpe_0171_100/d9zv9s8/ */ public enum ChunkTag { @@ -15,13 +15,14 @@ public enum ChunkTag { PENDING_TICKS((byte) 0x33),//TODO untested BLOCK_EXTRA_DATA((byte) 0x34),//TODO untested, 32768 bytes, used for top-snow. BIOME_STATE((byte) 0x35),//TODO untested - VERSION((byte) 0x76); - + GENERATOR_STAGE((byte) 0x36), + VERSION_PRE16((byte) 0x76), + VERSION((byte) 0x2c);; public final byte dataID; - ChunkTag(byte dataID){ + ChunkTag(byte dataID) { this.dataID = dataID; } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/NBTChunkData.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/NBTChunkData.java index ac685f61..5d78fbf6 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/NBTChunkData.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/NBTChunkData.java @@ -22,7 +22,8 @@ public NBTChunkData(Chunk chunk, ChunkTag dataType) { } public void load() throws WorldData.WorldDBLoadException, WorldData.WorldDBException, IOException { - loadFromByteArray(chunk.worldData.getChunkData(chunk.x, chunk.z, dataType, this.chunk.dimension, (byte) 0, false)); + Chunk chunk = this.chunk.get(); + loadFromByteArray(chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, dataType, chunk.mDimension, (byte) 0, false)); } public void loadFromByteArray(byte[] data) throws IOException { @@ -32,12 +33,13 @@ public void loadFromByteArray(byte[] data) throws IOException { public void write() throws WorldData.WorldDBException, IOException { if (this.tags == null) this.tags = new ArrayList<>(); byte[] data = DataConverter.write(this.tags); - this.chunk.worldData.writeChunkData(this.chunk.x, this.chunk.z, this.dataType, this.chunk.dimension, (byte) 0, false, data); + Chunk chunk = this.chunk.get(); + chunk.getWorldData().writeChunkData(chunk.mChunkX, chunk.mChunkZ, this.dataType, chunk.mDimension, (byte) 0, false, data); } @Override public void createEmpty() { - if(this.tags == null) this.tags = new ArrayList<>(); + if (this.tags == null) this.tags = new ArrayList<>(); this.tags.add(new IntTag("Placeholder", 42)); } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/PocketChunk.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/PocketChunk.java new file mode 100644 index 00000000..f4a9ec15 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/PocketChunk.java @@ -0,0 +1,223 @@ +/* +package com.mithrilmania.blocktopograph.chunk; + +import android.graphics.Color; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.map.Dimension; + +import java.nio.ByteBuffer; + +public final class PocketChunk extends Chunk { + + + private static final int POS_BLOCK_IDS = 0; + private static final int POS_META_DATA = 0x8000; + private static final int POS_SKY_LIGHT = 0xc000; + private static final int POS_BLOCK_LIGHT = 0x10000; + //Isn't this "dirty table"? + //Seems Proto got it wrong... + private static final int POS_HEIGHTMAP = 0x14000; + private static final int POS_BIOME_DATA = 0x14100; + private static final int LENGTH = 0x14500; + + private volatile ByteBuffer mData; + + PocketChunk(WorldData worldData, Version version, int chunkX, int chunkZ, Dimension dimension) { + super(worldData, version, chunkX, chunkZ, dimension); + tryLoad(); + } + + private void tryLoad() { + if (mData == null) { + try { + byte[] rawData = mWorldData.get().getChunkData(mChunkX, mChunkZ, ChunkTag.V0_9_LEGACY_TERRAIN, mDimension, (byte) 0, false); + if (rawData == null) { + mIsVoid = true; + return; + } + mData = ByteBuffer.allocate(rawData.length); + mData.put(rawData, 0, rawData.length); + mIsVoid = false; + } catch (Exception e) { + mIsError = true; + mIsVoid = true; + } + } + } + + public void createEmpty() { + byte[] chunk = new byte[LENGTH]; + int x, y, z, i = 0; + byte bedrock = (byte) 7; + byte sandstone = (byte) 24; + + //generate super basic terrain (one layer of bedrock, 31 layers of sandstone) + //Emmm but why + for (x = 0; x < 16; x++) { + for (z = 0; z < 16; z++) { + for (y = 0; y < 128; y++, i++) { + chunk[i] = (y == 0 ? bedrock : (y < 32 ? sandstone : 0)); + } + } + } + + //fill meta-data with 0 + for (; i < POS_SKY_LIGHT; i++) { + chunk[i] = 0; + } + + //fill blocklight with 0xff + for (; i < POS_BLOCK_LIGHT; i++) { + chunk[i] = (byte) 0xff; + } + + //fill block-light with 0xff + for (; i < POS_HEIGHTMAP; i++) { + chunk[i] = (byte) 0xff; + } + + //fill heightmap + for (; i < POS_BIOME_DATA; i++) { + chunk[i] = 32; + } + + //fill biome data + for (; i < LENGTH; ) { + chunk[i++] = 1;//biome: plains + chunk[i++] = (byte) 42;//r + chunk[i++] = (byte) 42;//g + chunk[i++] = (byte) 42;//b + } + + this.mData = ByteBuffer.wrap(chunk); + } + + private int getOffset(int x, int y, int z) { + // I prefer shifts than multiplies, prefer "bit or" than plus. + // I know compiler and Android runtime can optimize + // but this is cool, right?! + // No, not at all. I saw you filled the shift wrong and debugged for an hour one day. + return (((x << 4) | z) << 7) | y; + } + + private int get2dOffset(int x, int z) { + return (z << 4) | x; + } + + @Override + public boolean supportsBlockLightValues() { + return false; + } + + @Override + public boolean supportsHeightMap() { + return false; + } + + @Override + public int getHeightLimit() { + return 128; + } + + @Override + public int getHeightMapValue(int x, int z) { + if (x >= 16 || z >= 16 || x < 0 || z < 0 || mIsVoid) + return 0; + //There's no height map saved here! + //Do it the hard way! + for (int offset = POS_BLOCK_IDS + getOffset(x, 127, z), y = 127; y >= 0; y--, offset--) { + if (mData.get(offset) != 0) return y + 1; + } + return 0; + } + + @Override + public int getBiome(int x, int z) { + return mData.get(POS_BIOME_DATA + (get2dOffset(x, z) << 2)); + } + + @Override + public void setBiome(int x, int z, int id) { + mData.put(POS_BIOME_DATA + (get2dOffset(x, z) << 2), (byte) id); + } + + @Override + public int getGrassColor(int x, int z) { + int offset = POS_BIOME_DATA + (get2dOffset(x, z) << 2); + return Color.rgb(mData.get(offset + 1) & 0xff, mData.get(offset + 2) & 0xff, mData.get(offset + 3) & 0xff); + } + + @NonNull + @Override + public OldBlock getBlock(int x, int y, int z) { + return getBlock(x, y, z, 0); + } + + @NonNull + @Override + public OldBlock getBlock(int x, int y, int z, int layer) { + return mWorldData.get().mOldBlockRegistry.createBlock(getKnownBlock(x, y, z, layer)); + } + + @NonNull + private KnownBlockRepr getKnownBlock(int x, int y, int z, int layer) { + if (x >= 16 || y >= 128 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return KnownBlockRepr.B_0_0_AIR; + int offset = getOffset(x, y, z); + int id = mData.get(POS_BLOCK_IDS + offset) & 0xff; + int data = mData.get(POS_META_DATA + (offset >>> 1)); + data = (offset & 1) == 1 ? ((data >>> 4) & 0xf) : (data & 0xf); + return KnownBlockRepr.getBestBlock(id, data); + } + + @Override + public void setBlock(int x, int y, int z, int layer, @NonNull OldBlock oldBlock) { + //TODO implement setBlock for pocket chunk + } + + @Override + public int getBlockLightValue(int x, int y, int z) { + if (x >= 16 || y >= 128 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return 0; + int offset = getOffset(x, y, z); + int dualData = mData.get(POS_BLOCK_LIGHT + (offset >>> 1)); + return (offset & 1) == 1 ? (dualData >>> 4) & 0xf : dualData & 0xf; + } + + @Override + public int getSkyLightValue(int x, int y, int z) { + if (x >= 16 || y >= 128 || z >= 16 || x < 0 || y < 0 || z < 0 || mIsVoid) + return 0; + int offset = getOffset(x, y, z); + int dualData = mData.get(POS_SKY_LIGHT + (offset >>> 1)); + return (offset & 1) == 1 ? (dualData >>> 4) & 0xf : dualData & 0xf; + } + + @Override + public int getHighestBlockYUnderAt(int x, int z, int y) { + for (int yy = y; yy >= 0; yy--) { + if (getKnownBlock(x & 0xf, yy, z & 0xf, 0) != KnownBlockRepr.B_0_0_AIR) return yy; + } + return -1; + } + + @Override + public int getCaveYUnderAt(int x, int z, int y) { + for (int yy = y; yy >= 0; yy--) { + if (getKnownBlock(x & 0xf, yy, z & 0xf, 0) == KnownBlockRepr.B_0_0_AIR) return yy; + } + return -1; + } + + @Override + public void save() { + // TODO implement save for pocket chunk + if (mIsError || mIsVoid) return; + } +} +*/ diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Version.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Version.java index 5d3c57d7..5d0386d3 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Version.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/Version.java @@ -3,12 +3,9 @@ import android.util.SparseArray; -import com.mithrilmania.blocktopograph.Log; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; -import com.mithrilmania.blocktopograph.chunk.terrain.V0_9_TerrainChunkData; -import com.mithrilmania.blocktopograph.chunk.terrain.V1_0_TerrainChunkData; -import com.mithrilmania.blocktopograph.chunk.terrain.V1_1_TerrainChunkData; -import com.mithrilmania.blocktopograph.util.ConvertUtil; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + public enum Version { @@ -17,15 +14,17 @@ public enum Version { OLD_LIMITED("v0.2.0", "classic mcpe, 16x16x16x16x18 world, level.dat; introduced in v0.2.0", 1, 128, 1), v0_9("v0.9.0", "infinite xz, zlib leveldb; introduced in v0.9.0", 2, 128, 1), V1_0("v1.0.0", "Stacked sub-chunks, 256 world-height, 16 high sub-chunks; introduced in alpha v1.0.0 (v0.17)", 3, 16, 16), - V1_1("v1.1.0", "Block-light is not stored anymore", 4, 16, 16); + V1_1("v1.1.0", "KnownBlockRepr-light is not stored anymore", 4, 16, 16), + V1_2_PLUS("v1.2.0.13", "Global numeric id replaced with string id and per-chunk numeric id", 7, 16, 16), + V1_16_PLUS("v1.16(17)", "val is replaced by block states",0x16,16,16); - public static final int LATEST_SUPPORTED_VERSION = V1_1.id; + public static final int LATEST_SUPPORTED_VERSION = V1_16_PLUS.id; public final String displayName, description; public final int id, subChunkHeight, subChunks; - Version(String displayName, String description, int id, int subChunkHeight, int subChunks){ + Version(String displayName, String description, int id, int subChunkHeight, int subChunks) { this.displayName = displayName; this.description = description; this.id = id; @@ -34,25 +33,29 @@ public enum Version { } private static final SparseArray versionMap; + static { versionMap = new SparseArray<>(); - for(Version b : Version.values()){ + for (Version b : Version.values()) { versionMap.put(b.id, b); } } - public static Version getVersion(byte[] data){ + + @NonNull + public static Version getVersion(@Nullable byte[] data) { //Log.d("Data version: "+ ConvertUtil.bytesToHexStr(data)); //`data` is supposed to be one byte, // but it might grow to contain more data later on, or larger version ids. // Looking up the first byte is sufficient for now. - if(data == null || data.length <= 0) { + if (data == null || data.length <= 0) { return NULL; } else { int versionNumber = data[0] & 0xff; //fallback version - if(versionNumber > LATEST_SUPPORTED_VERSION) { + //You can't just do this... + if (versionNumber > LATEST_SUPPORTED_VERSION) { versionNumber = LATEST_SUPPORTED_VERSION; } @@ -62,27 +65,9 @@ public static Version getVersion(byte[] data){ } } - public TerrainChunkData createTerrainChunkData(Chunk chunk, byte subChunk) throws VersionException { - switch (this){ - case ERROR: - case NULL: - return null; - case OLD_LIMITED: - throw new VersionException("Handling terrain chunk data is NOT supported for this version!", this); - case v0_9: - return new V0_9_TerrainChunkData(chunk, subChunk); - case V1_0: - return new V1_0_TerrainChunkData(chunk, subChunk); - case V1_1: - return new V1_1_TerrainChunkData(chunk, subChunk); - default: - //use the latest version, like nothing will ever happen... - return new V1_1_TerrainChunkData(chunk, subChunk); - } - } - + @Nullable public NBTChunkData createEntityChunkData(Chunk chunk) throws VersionException { - switch (this){ + switch (this) { case ERROR: case NULL: return null; @@ -94,8 +79,9 @@ public NBTChunkData createEntityChunkData(Chunk chunk) throws VersionException { } } + @Nullable public NBTChunkData createBlockEntityChunkData(Chunk chunk) throws VersionException { - switch (this){ + switch (this) { case ERROR: case NULL: return null; @@ -107,14 +93,16 @@ public NBTChunkData createBlockEntityChunkData(Chunk chunk) throws VersionExcept } } + @NonNull + @Override - public String toString(){ - return "[MCPE version \""+displayName+"\" (version-code: "+id+")]"; + public String toString() { + return "[MCPE version \"" + displayName + "\" (version-code: " + id + ")]"; } public static class VersionException extends Exception { - VersionException(String msg, Version version){ + VersionException(String msg, @NonNull Version version) { super(msg + " " + version.toString()); } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/VoidChunk.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/VoidChunk.java new file mode 100644 index 00000000..6c521804 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/VoidChunk.java @@ -0,0 +1,94 @@ +package com.mithrilmania.blocktopograph.chunk; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.Block; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.map.Dimension; + + +public final class VoidChunk extends Chunk { + + VoidChunk(WorldData worldData, Version version, int chunkX, int chunkZ, Dimension dimension) { + super(worldData, version, chunkX, chunkZ, dimension); + mIsVoid = true; + } + + @Override + public boolean supportsBlockLightValues() { + return false; + } + + @Override + public boolean supportsHeightMap() { + return false; + } + + @Override + public int getHeightLimit() { + return 0; + } + + @Override + public int getHeightMapValue(int x, int z) { + return 0; + } + + @Override + public int getBiome(int x, int z) { + return 0; + } + + @Override + public void setBiome(int x, int z, int id) { + } + + @Override + public int getGrassColor(int x, int z) { + return 0; + } + + @NonNull + @Override + public BlockTemplate getBlockTemplate(int x, int y, int z, int layer) { + return BlockTemplates.getAirTemplate(); + } + + @NonNull + @Override + public Block getBlock(int x, int y, int z, int layer) { + throw new RuntimeException(); + } + + @Override + public void setBlock(int x, int y, int z, int layer, @NonNull Block block) { + throw new RuntimeException(); + } + + @Override + public int getBlockLightValue(int x, int y, int z) { + return 0; + } + + @Override + public int getSkyLightValue(int x, int y, int z) { + return 0; + } + + @Override + public int getHighestBlockYUnderAt(int x, int z, int y) { + return -1; + } + + @Override + public int getCaveYUnderAt(int x, int z, int y) { + return -1; + } + + @Override + public void save() { + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/PreV1d2d13TerrainSubChunk.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/PreV1d2d13TerrainSubChunk.java new file mode 100644 index 00000000..3cb23bb6 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/PreV1d2d13TerrainSubChunk.java @@ -0,0 +1,77 @@ +/* +package com.mithrilmania.blocktopograph.chunk.terrain; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.block.OldBlockRegistry; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.map.Dimension; + +import java.nio.ByteBuffer; + +public final class PreV1d2d13TerrainSubChunk extends TerrainSubChunk { + + private static final int POS_BLOCK_IDS = 1; + private static final int POS_META_DATA = 0x1001; + private static final int POS_SKY_LIGHT = 0x1801; + private static final int POS_BLOCK_LIGHT = 0x2001; + private static final int TERRAIN_MAX_LENGTH = 0x2801; + + private ByteBuffer mData; + + PreV1d2d13TerrainSubChunk(@NonNull ByteBuffer raw, @NonNull OldBlockRegistry oldBlockRegistry) { + + super(oldBlockRegistry); + + int size = raw.capacity(); + if (size < POS_SKY_LIGHT || size > TERRAIN_MAX_LENGTH) { + mIsError = true; + return; + } + mIsError = false; + mData = ByteBuffer.allocate(size); + mData.put(raw); + mHasSkyLight = size >= POS_BLOCK_LIGHT; + mHasBlockLight = size == TERRAIN_MAX_LENGTH; + } + + @NonNull + @Override + public OldBlock getBlock(int x, int y, int z, int layer) { + if (mIsError) return getAir(); + int offset = getOffset(x, y, z); + int id = mData.get(POS_BLOCK_IDS + offset) & 0xff; + int data = mData.get(POS_META_DATA + (offset >>> 1)); + data = (offset & 1) == 1 ? ((data >>> 4) & 0xf) : (data & 0xf); + return wrapKnownBlock(KnownBlockRepr.getBestBlock(id, data)); + } + + @Override + public void setBlock(int x, int y, int z, int layer, @NonNull OldBlock oldBlock) { + // TODO implement setBlock for pre v1.2.13 subChunk. + } + + @Override + public int getBlockLightValue(int x, int y, int z) { + if (mIsError || !mHasBlockLight) return 0; + int offset = getOffset(x, y, z); + int dualData = mData.get(POS_BLOCK_LIGHT + (offset >>> 1)); + return (offset & 1) == 1 ? (dualData >>> 4) & 0xf : dualData & 0xf; + } + + @Override + public int getSkyLightValue(int x, int y, int z) { + if (mIsError || !mHasSkyLight) return 0; + int offset = getOffset(x, y, z); + int dualData = mData.get(POS_SKY_LIGHT + (offset >>> 1)); + return (offset & 1) == 1 ? (dualData >>> 4) & 0xf : dualData & 0xf; + } + + @Override + public void save(WorldData worldData, int chunkX, int chunkZ, Dimension dimension, int which) { + // TODO implement save for pre v1.2.13 subChunk. + } +} +*/ diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/TerrainChunkData.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/TerrainChunkData.java index 83954845..e91b0a4c 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/TerrainChunkData.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/TerrainChunkData.java @@ -2,17 +2,25 @@ import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.ChunkData; +import com.mithrilmania.blocktopograph.util.Noise; public abstract class TerrainChunkData extends ChunkData { public final byte subChunk; + protected boolean mNotFailed; + public TerrainChunkData(Chunk chunk, byte subChunk) { super(chunk); + this.mNotFailed = true; this.subChunk = subChunk; } + public final boolean hasNotFailed() { + return mNotFailed; + } + public abstract boolean loadTerrain(); public abstract boolean load2DData(); @@ -41,5 +49,21 @@ public TerrainChunkData(Chunk chunk, byte subChunk) { public abstract int getHeightMapValue(int x, int z); - + protected int getNoise(int base, int x, int z) { + // noise values are between -1 and 1 + // 0.0001 is added to the coordinates because integer values result in 0 + Chunk chunk = this.chunk.get(); + double oct1 = Noise.noise( + ((double) (chunk.mChunkX * 16 + x) / 100.0) + 0.0001, + ((double) (chunk.mChunkZ * 16 + z) / 100.0) + 0.0001); + double oct2 = Noise.noise( + ((double) (chunk.mChunkX * 16 + x) / 20.0) + 0.0001, + ((double) (chunk.mChunkZ * 16 + z) / 20.0) + 0.0001); + double oct3 = Noise.noise( + ((double) (chunk.mChunkX * 16 + x) / 3.0) + 0.0001, + ((double) (chunk.mChunkZ * 16 + z) / 3.0) + 0.0001); + return (int) (base + 60 + (40 * oct1) + (14 * oct2) + (6 * oct3)); + } + + } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/TerrainSubChunk.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/TerrainSubChunk.java new file mode 100644 index 00000000..9940a14d --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/TerrainSubChunk.java @@ -0,0 +1,117 @@ +package com.mithrilmania.blocktopograph.chunk.terrain; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.Block; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.map.Dimension; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public abstract class TerrainSubChunk { + +// private final WeakReference mBlockRegistry; + + boolean mHasSkyLight; + boolean mHasBlockLight; + boolean mIsError; + + protected TerrainSubChunk() { +// mBlockRegistry = new WeakReference<>(oldBlockRegistry); + } + + @Nullable + public static TerrainSubChunk create(@NonNull byte[] rawData) { + TerrainSubChunk subChunk; + ByteBuffer byteBuffer = ByteBuffer.wrap(rawData); + switch (rawData[0]) { +// case 0: +// case 2: +// case 3: +// case 4: +// case 5: +// case 6: +// case 7: +// subChunk = new PreV1d2d13TerrainSubChunk(byteBuffer, oldBlockRegistry); +// break; + case 1: + case 8: + subChunk = new V1d2d13TerrainSubChunk(byteBuffer); + break; + default: + subChunk = null; + } + return subChunk; + } + + @Nullable + public static TerrainSubChunk createEmpty(int preferredVersion) { + TerrainSubChunk subChunk; + switch (preferredVersion) { + case 0: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + subChunk = null; + break; + case 1: + case 8: + subChunk = new V1d2d13TerrainSubChunk(); + break; + default: + subChunk = null; + } + return subChunk; + } + +// @NonNull +// protected OldBlock wrapKnownBlock(KnownBlockRepr knownBlock) { +// // TODO: This would be not efficiency for old saves, add corresponding oldBlock to known blocks. +// return mBlockRegistry.get().createBlock(knownBlock); +// } + + @NonNull + abstract public BlockTemplate getBlockTemplate(int x, int y, int z, int layer); + + @NonNull + abstract public Block getBlock(int x, int y, int z, int layer); + + abstract public void setBlock(int x, int y, int z, int layer, @NonNull Block block); + + abstract public int getBlockLightValue(int x, int y, int z); + + abstract public int getSkyLightValue(int x, int y, int z); + + protected static final int getOffset(int x, int y, int z) { + return (((x << 4) | z) << 4) | y; + } + + + public final boolean hasBlockLight() { + return mHasBlockLight; + } + + + public final boolean isError() { + return mIsError; + } + +// @Nullable +// protected OldBlockRegistry getBlockRegistry() { +// OldBlockRegistry oldBlockRegistry = mBlockRegistry.get(); +// if (oldBlockRegistry == null) { +// mIsError = true; +// } +// return oldBlockRegistry; +// } + + abstract public void save(WorldData worldData, int chunkX, int chunkZ, Dimension dimension, int which) throws WorldData.WorldDBException, IOException; + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V0_9_TerrainChunkData.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V0_9_TerrainChunkData.java index ca177522..7838fec8 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V0_9_TerrainChunkData.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V0_9_TerrainChunkData.java @@ -1,3 +1,4 @@ +/* package com.mithrilmania.blocktopograph.chunk.terrain; import com.mithrilmania.blocktopograph.WorldData; @@ -31,36 +32,38 @@ public class V0_9_TerrainChunkData extends TerrainChunkData { public V0_9_TerrainChunkData(Chunk chunk, byte subChunk) { super(chunk, subChunk); + mNotFailed = tryLoad(); } @Override public void write() throws IOException, WorldData.WorldDBException { - this.chunk.worldData.writeChunkData(chunk.x, chunk.z, ChunkTag.V0_9_LEGACY_TERRAIN, chunk.dimension, subChunk, false, toByteArray()); + Chunk chunk = this.chunk.get(); + chunk.getWorldData().writeChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.V0_9_LEGACY_TERRAIN, chunk.mDimension, subChunk, false, toByteArray()); } @Override - public boolean loadTerrain(){ - return tryLoad(); + public boolean loadTerrain() { + return mNotFailed; } @Override - public boolean load2DData(){ - return tryLoad(); + public boolean load2DData() { + return mNotFailed; } public boolean tryLoad() { - if(buf == null){ + if (buf == null) { try { - byte[] rawData = this.chunk.worldData.getChunkData(chunk.x, chunk.z, ChunkTag.V0_9_LEGACY_TERRAIN, chunk.dimension, subChunk, false); - if(rawData == null) return false; + Chunk chunk = this.chunk.get(); + byte[] rawData = chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.V0_9_LEGACY_TERRAIN, chunk.mDimension, subChunk, false); + if (rawData == null) return false; this.buf = ByteBuffer.wrap(rawData); return true; - } catch (Exception e){ + } catch (Exception e) { //data is not present return false; } - } - else return true; + } else return true; } public byte[] toByteArray() throws IOException { @@ -77,36 +80,36 @@ public void createEmpty() { byte sandstone = (byte) 24; //generate super basic terrain (one layer of bedrock, 31 layers of sandstone) - for(x = 0; x < chunkW; x++){ - for(z = 0; z < chunkL; z++){ - for(y = 0; y < chunkH; y++, i++){ + for (x = 0; x < chunkW; x++) { + for (z = 0; z < chunkL; z++) { + for (y = 0; y < chunkH; y++, i++) { chunk[i] = (y == 0 ? bedrock : (y < 32 ? sandstone : 0)); } } } //fill meta-data with 0 - for(; i < POS_SKY_LIGHT; i++){ + for (; i < POS_SKY_LIGHT; i++) { chunk[i] = 0; } //fill blocklight with 0xff - for(; i < POS_BLOCK_LIGHT; i++){ + for (; i < POS_BLOCK_LIGHT; i++) { chunk[i] = (byte) 0xff; } //fill block-light with 0xff - for(; i < POS_HEIGHTMAP; i++){ + for (; i < POS_HEIGHTMAP; i++) { chunk[i] = (byte) 0xff; } //fill heightmap - for(; i < POS_BIOME_DATA; i++){ + for (; i < POS_BIOME_DATA; i++) { chunk[i] = 32; } //fill biome data - for(; i < LENGTH;){ + for (; i < LENGTH; ) { chunk[i++] = 1;//biome: plains chunk[i++] = (byte) 42;//r chunk[i++] = (byte) 42;//g @@ -161,9 +164,11 @@ public boolean supportsBlockLightValues() { return true; } - /** + */ +/** * Sets a block type, and also set the corresponding dirty table entry and set the saving flag. - */ + *//* + @Override public void setBlockTypeId(int x, int y, int z, int type) { if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { @@ -221,3 +226,4 @@ public int getHeightMapValue(int x, int z) { } } +*/ diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_0_TerrainChunkData.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_0_TerrainChunkData.java index a31cb3b5..8d1eda7a 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_0_TerrainChunkData.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_0_TerrainChunkData.java @@ -1,11 +1,10 @@ +/* package com.mithrilmania.blocktopograph.chunk.terrain; import com.mithrilmania.blocktopograph.WorldData; import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.ChunkTag; -import com.mithrilmania.blocktopograph.chunk.Version; import com.mithrilmania.blocktopograph.map.Biome; -import com.mithrilmania.blocktopograph.util.Noise; import java.nio.ByteBuffer; @@ -33,44 +32,46 @@ public class V1_0_TerrainChunkData extends TerrainChunkData { public V1_0_TerrainChunkData(Chunk chunk, byte subChunk) { super(chunk, subChunk); + mNotFailed = loadTerrain(); } @Override public void write() throws WorldData.WorldDBException { - this.chunk.worldData.writeChunkData(chunk.x, chunk.z, ChunkTag.TERRAIN, chunk.dimension, subChunk, true, terrainData.array()); - this.chunk.worldData.writeChunkData(chunk.x, chunk.z, ChunkTag.DATA_2D, chunk.dimension, subChunk, true, data2D.array()); + Chunk chunk = this.chunk.get(); + chunk.getWorldData().writeChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.TERRAIN, chunk.mDimension, subChunk, true, terrainData.array()); + chunk.getWorldData().writeChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.DATA_2D, chunk.mDimension, subChunk, true, data2D.array()); } @Override public boolean loadTerrain() { - if(terrainData == null){ + if (terrainData == null) { try { - byte[] rawData = this.chunk.worldData.getChunkData(chunk.x, chunk.z, ChunkTag.TERRAIN, chunk.dimension, subChunk, true); - if(rawData == null) return false; + Chunk chunk = this.chunk.get(); + byte[] rawData = chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.TERRAIN, chunk.mDimension, subChunk, true); + if (rawData == null) return false; this.terrainData = ByteBuffer.wrap(rawData); return true; - } catch (Exception e){ + } catch (Exception e) { //data is not present return false; } - } - else return true; + } else return mNotFailed; } @Override public boolean load2DData() { - if(data2D == null){ + if (data2D == null) { try { - byte[] rawData = this.chunk.worldData.getChunkData(chunk.x, chunk.z, ChunkTag.DATA_2D, chunk.dimension, subChunk, false); - if(rawData == null) return false; + Chunk chunk = this.chunk.get(); + byte[] rawData = chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.DATA_2D, chunk.mDimension, subChunk, false); + if (rawData == null) return false; this.data2D = ByteBuffer.wrap(rawData); return true; - } catch (Exception e){ + } catch (Exception e) { //data is not present return false; } - } - else return true; + } else return true; } @@ -87,9 +88,9 @@ public void createEmpty() { byte sandstone = (byte) 24; //generate super basic terrain (one layer of bedrock, 31 layers of sandstone) - for(x = 0; x < chunkW; x++){ - for(z = 0; z < chunkL; z++){ - for(y = 0, realY = chunkH * this.subChunk; y < chunkH; y++, i++, realY++){ + for (x = 0; x < chunkW; x++) { + for (z = 0; z < chunkL; z++) { + for (y = 0, realY = chunkH * this.subChunk; y < chunkH; y++, i++, realY++) { terrain[i] = (realY == 0 ? bedrock : (realY < 32 ? sandstone : 0)); } } @@ -97,17 +98,17 @@ public void createEmpty() { //fill meta-data with 0 - for(; i < POS_META_DATA; i++){ + for (; i < POS_META_DATA; i++) { terrain[i] = (byte) 0; } //fill blocklight with 0xff - for(; i < POS_BLOCK_LIGHT; i++){ + for (; i < POS_BLOCK_LIGHT; i++) { terrain[i] = (byte) 0xff; } //fill block-light with 0xff - for(; i < TERRAIN_LENGTH; i++){ + for (; i < TERRAIN_LENGTH; i++) { terrain[i] = (byte) 0xff; } @@ -115,18 +116,18 @@ public void createEmpty() { i = 0; - if(this.subChunk == (byte) 0){ + if (this.subChunk == (byte) 0) { byte[] data2d = new byte[DATA2D_LENGTH]; //fill heightmap - for(; i < POS_BIOME_DATA;){ + for (; i < POS_BIOME_DATA; ) { data2d[i++] = 0; data2d[i++] = 32; } //fill biome data - for(; i < DATA2D_LENGTH;){ + for (; i < DATA2D_LENGTH; ) { data2d[i++] = 1;//biome: plains data2d[i++] = (byte) 42;//r data2d[i++] = (byte) 42;//g @@ -183,9 +184,11 @@ public boolean supportsBlockLightValues() { return true; } - /** + */ +/** * Sets a block type, and also set the corresponding dirty table entry and set the saving flag. - */ + *//* + @Override public void setBlockTypeId(int x, int y, int z, int type) { if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { @@ -218,25 +221,12 @@ public byte getBiome(int x, int z) { return data2D.get(POS_BIOME_DATA + get2Di(x, z)); } - private int getNoise(int base, int x, int z){ - // noise values are between -1 and 1 - // 0.0001 is added to the coordinates because integer values result in 0 - double oct1 = Noise.noise( - ((double) (this.chunk.x * chunkW + x) / 100.0) + 0.0001, - ((double) (this.chunk.z * chunkL + z) / 100.0) + 0.0001); - double oct2 = Noise.noise( - ((double) (this.chunk.x * chunkW + x) / 20.0) + 0.0001, - ((double) (this.chunk.z * chunkL + z) / 20.0) + 0.0001); - double oct3 = Noise.noise( - ((double) (this.chunk.x * chunkW + x) / 3.0) + 0.0001, - ((double) (this.chunk.z * chunkL + z) / 3.0) + 0.0001); - return (int) (base + 60 + (40 * oct1) + (14 * oct2) + (6 * oct3)); - } - - /* + */ +/* MCPE 1.0 stopped embedding foliage color data in the chunk data, so now we fake the colors by combining biome colors with Perlin noise - */ + *//* + @Override public byte getGrassR(int x, int z) { @@ -269,3 +259,4 @@ public int getHeightMapValue(int x, int z) { return ((h & 0xff) << 8) | ((h >> 8) & 0xff);//little endian to big endian } } +*/ diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_1_TerrainChunkData.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_1_TerrainChunkData.java index 6d9dc4c4..e838c7cf 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_1_TerrainChunkData.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_1_TerrainChunkData.java @@ -1,10 +1,10 @@ +/* package com.mithrilmania.blocktopograph.chunk.terrain; import com.mithrilmania.blocktopograph.WorldData; import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.ChunkTag; import com.mithrilmania.blocktopograph.map.Biome; -import com.mithrilmania.blocktopograph.util.Noise; import java.nio.ByteBuffer; @@ -31,44 +31,46 @@ public class V1_1_TerrainChunkData extends TerrainChunkData { public V1_1_TerrainChunkData(Chunk chunk, byte subChunk) { super(chunk, subChunk); + mNotFailed = loadTerrain(); } @Override public void write() throws WorldData.WorldDBException { - this.chunk.worldData.writeChunkData(chunk.x, chunk.z, ChunkTag.TERRAIN, chunk.dimension, subChunk, true, terrainData.array()); - this.chunk.worldData.writeChunkData(chunk.x, chunk.z, ChunkTag.DATA_2D, chunk.dimension, subChunk, true, data2D.array()); + Chunk chunk = this.chunk.get(); + chunk.getWorldData().writeChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.TERRAIN, chunk.mDimension, subChunk, true, terrainData.array()); + chunk.getWorldData().writeChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.DATA_2D, chunk.mDimension, subChunk, true, data2D.array()); } @Override public boolean loadTerrain() { - if(terrainData == null){ + if (terrainData == null) { try { - byte[] rawData = this.chunk.worldData.getChunkData(chunk.x, chunk.z, ChunkTag.TERRAIN, chunk.dimension, subChunk, true); - if(rawData == null) return false; + Chunk chunk = this.chunk.get(); + byte[] rawData = chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.TERRAIN, chunk.mDimension, subChunk, true); + if (rawData == null) return false; this.terrainData = ByteBuffer.wrap(rawData); return true; - } catch (Exception e){ + } catch (Exception e) { //data is not present return false; } - } - else return true; + } else return mNotFailed; } @Override public boolean load2DData() { - if(data2D == null){ + if (data2D == null) { try { - byte[] rawData = this.chunk.worldData.getChunkData(chunk.x, chunk.z, ChunkTag.DATA_2D, chunk.dimension, subChunk, false); - if(rawData == null) return false; + Chunk chunk = this.chunk.get(); + byte[] rawData = chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.DATA_2D, chunk.mDimension, subChunk, false); + if (rawData == null) return false; this.data2D = ByteBuffer.wrap(rawData); return true; - } catch (Exception e){ + } catch (Exception e) { //data is not present return false; } - } - else return true; + } else return true; } @@ -85,9 +87,9 @@ public void createEmpty() { byte sandstone = (byte) 24; //generate super basic terrain (one layer of bedrock, 31 layers of sandstone) - for(x = 0; x < chunkW; x++){ - for(z = 0; z < chunkL; z++){ - for(y = 0, realY = chunkH * this.subChunk; y < chunkH; y++, i++, realY++){ + for (x = 0; x < chunkW; x++) { + for (z = 0; z < chunkL; z++) { + for (y = 0, realY = chunkH * this.subChunk; y < chunkH; y++, i++, realY++) { terrain[i] = (realY == 0 ? bedrock : (realY < 32 ? sandstone : 0)); } } @@ -95,12 +97,12 @@ public void createEmpty() { //fill meta-data with 0 - for(; i < POS_META_DATA; i++){ + for (; i < POS_META_DATA; i++) { terrain[i] = (byte) 0; } //fill block-light with 0xff - for(; i < TERRAIN_LENGTH; i++){ + for (; i < TERRAIN_LENGTH; i++) { terrain[i] = (byte) 0xff; } @@ -108,18 +110,18 @@ public void createEmpty() { i = 0; - if(this.subChunk == (byte) 0){ + if (this.subChunk == (byte) 0) { byte[] data2d = new byte[DATA2D_LENGTH]; //fill heightmap - for(; i < POS_BIOME_DATA;){ + for (; i < POS_BIOME_DATA; ) { data2d[i++] = 0; data2d[i++] = 32; } //fill biome data - for(; i < DATA2D_LENGTH;){ + for (; i < DATA2D_LENGTH; ) { data2d[i++] = 1;//biome: plains data2d[i++] = (byte) 42;//r data2d[i++] = (byte) 42;//g @@ -152,8 +154,7 @@ public byte getBlockData(int x, int y, int z) { //dualData = terrainData.get(POS_META_DATA + (offset >>> 1)); dualData = terrainData.get(terrainData.limit() - (offset >>> 1)); return (byte) ((offset & 1) == 1 ? ((dualData >>> 4) & 0xf) : (dualData & 0xf)); - } - catch (Exception e) { + } catch (Exception e) { return (byte) ((offset & 1) == 1 ? ((dualData >>> 4) & 0xf) : (dualData & 0xf)); } @@ -181,9 +182,11 @@ public boolean supportsBlockLightValues() { return false; } - /** + */ +/** * Sets a block type, and also set the corresponding dirty table entry and set the saving flag. - */ + *//* + @Override public void setBlockTypeId(int x, int y, int z, int type) { if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { @@ -216,25 +219,12 @@ public byte getBiome(int x, int z) { return data2D.get(POS_BIOME_DATA + get2Di(x, z)); } - private int getNoise(int base, int x, int z){ - // noise values are between -1 and 1 - // 0.0001 is added to the coordinates because integer values result in 0 - double oct1 = Noise.noise( - ((double) (this.chunk.x * chunkW + x) / 100.0) + 0.0001, - ((double) (this.chunk.z * chunkL + z) / 100.0) + 0.0001); - double oct2 = Noise.noise( - ((double) (this.chunk.x * chunkW + x) / 20.0) + 0.0001, - ((double) (this.chunk.z * chunkL + z) / 20.0) + 0.0001); - double oct3 = Noise.noise( - ((double) (this.chunk.x * chunkW + x) / 3.0) + 0.0001, - ((double) (this.chunk.z * chunkL + z) / 3.0) + 0.0001); - return (int) (base + 60 + (40 * oct1) + (14 * oct2) + (6 * oct3)); - } - - /* + */ +/* MCPE 1.0 stopped embedding foliage color data in the chunk data, so now we fake the colors by combining biome colors with Perlin noise - */ + *//* + @Override public byte getGrassR(int x, int z) { @@ -267,3 +257,4 @@ public int getHeightMapValue(int x, int z) { return ((h & 0xff) << 8) | ((h >> 8) & 0xff);//little endian to big endian } } +*/ diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_2_Plus_TerrainChunkData.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_2_Plus_TerrainChunkData.java new file mode 100644 index 00000000..655b493b --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1_2_Plus_TerrainChunkData.java @@ -0,0 +1,304 @@ +/* +package com.mithrilmania.blocktopograph.chunk.terrain; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.chunk.Chunk; +import com.mithrilmania.blocktopograph.chunk.ChunkTag; +import com.mithrilmania.blocktopograph.map.Biome; +import com.mithrilmania.blocktopograph.nbt.convert.NBTInputStream; +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.ShortTag; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; + +public class V1_2_Plus_TerrainChunkData extends TerrainChunkData { + + //There could be multiple BlockStorage but we can just display the main. + public volatile IntBuffer mainStorage; + public volatile ByteBuffer data2D; + public volatile List palette; + public volatile int blockTypes, blockCodeLenth; + + public static final int chunkW = 16, chunkL = 16, chunkH = 16; + + public static final int area = chunkW * chunkL; + public static final int vol = area * chunkH; + + public static final int POS_HEIGHTMAP = 0; + // it looks like each biome takes 2 bytes, and the first 1 byte of every 2 bytes is always 0!? + public static final int POS_BIOME_DATA = POS_HEIGHTMAP + area + area; + public static final int DATA2D_LENGTH = POS_BIOME_DATA + area; + + //Masks used to extract BlockState bits of a certain oldBlock out of a int32, and vice-versa. + private static final int[] msk = {0b1, 0b11, 0b111, 0b1111, 0b11111, 0b111111, 0b1111111, + 0b11111111, + 0b111111111, 0b1111111111, 0b11111111111, + 0b111111111111, + 0b1111111111111, 0b11111111111111, 0b11111111111111}; + + public V1_2_Plus_TerrainChunkData(Chunk chunk, byte subChunk) { + super(chunk, subChunk); + mNotFailed = loadTerrain(); + } + + @Override + public void write() throws WorldData.WorldDBException { + Chunk chunk = this.chunk.get(); + //this.chunk.worldData.get().writeChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.TERRAIN, chunk.mDimension, subChunk, true, terrainData.array()); + chunk.getWorldData().writeChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.DATA_2D, chunk.mDimension, subChunk, true, data2D.array()); + } + + @Override + public boolean loadTerrain() { + //Don't repeat the work. + if (mainStorage == null) { + try { + //Retrieve raw data from database. + Chunk chunk = this.chunk.get(); + byte[] rawData = chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.TERRAIN, chunk.mDimension, subChunk, true); + if (rawData == null) return false; + ByteBuffer raw = ByteBuffer.wrap(rawData); + raw.order(ByteOrder.LITTLE_ENDIAN); + + //The first byte indicates version. + switch (rawData[0]) { + //1: Only one BlockStorage starting from the next byte. + case 1: + raw.position(1); + break; + //8: One or more BlockStorage's, next byte is the count. We only read the first. + case 8: + raw.position(2); + break; + //0,2,3,4,5,6,7: Should use a V1_1 terrain, why reaching here? + //Else: wtf? + default: + return false; + } + + //Load the BlockStorage. + loadBlockStorage(raw); + return true; + } catch (Exception e) { + //data is not present + return false; + } + } else return mNotFailed; + } + + private void loadBlockStorage(ByteBuffer raw) throws IOException { + + //Read BlockState length. + //this byte = (length << 2) | serializedType. + blockCodeLenth = (raw.get() & 0xff) >> 1; + + //We use this much of bytes to store BlockStates. + int bufsize = (4095 / (32 / blockCodeLenth) + 1) << 2; + ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize); + byteBuffer.order(ByteOrder.LITTLE_ENDIAN); + mainStorage = byteBuffer.asIntBuffer(); + + //No convenient way copy these stuff. + byteBuffer.put(raw.array(), raw.position(), bufsize); + raw.position(raw.position() + bufsize); + + //Palette items count. + int psize = raw.getInt(); + + //Construct the palette. Each item is a piece of nbt data. + palette = new ArrayList<>(16); + + //NBT reader requires a stream. + ByteArrayInputStream bais = new ByteArrayInputStream(raw.array()); + bais.skip(raw.position()); + + //Wrap it. + NBTInputStream nis = new NBTInputStream(bais, false); + for (int i = 0; i < psize; i++) { + + //Read a piece of nbt data, represented by a root CompoundTag. + CompoundTag tag = (CompoundTag) nis.readTag(); + + //Read `name` and `val` then resolve the `name` into numeric id. + String name = ((StringTag) tag.getChildTagByKey("name")).getValue(); + int data = ((ShortTag) tag.getChildTagByKey("val")).getValue(); + palette.add( +// BlockNameResolver.resolve(name) + KnownBlockRepr.resolve(name) + << 8 | data); + } + + //If one day we need to read more BlockStorage's, this line helps. + raw.position(raw.position() + nis.getReadCount()); + } + + @Override + public boolean load2DData() { + if (data2D == null) { + try { + Chunk chunk = this.chunk.get(); + byte[] rawData = chunk.getWorldData().getChunkData(chunk.mChunkX, chunk.mChunkZ, ChunkTag.DATA_2D, chunk.mDimension, subChunk, false); + if (rawData == null) return false; + this.data2D = ByteBuffer.wrap(rawData); + return true; + } catch (Exception e) { + //data is not present + return false; + } + } else return true; + } + + + @Override + public void createEmpty() { + + int i = 0; + + if (this.subChunk == (byte) 0) { + + byte[] data2d = new byte[DATA2D_LENGTH]; + + //fill heightmap + for (; i < POS_BIOME_DATA; ) { + data2d[i++] = 0; + data2d[i++] = 32; + } + + //fill biome data + for (; i < DATA2D_LENGTH; ) { + data2d[i++] = 1;//biome: plains + data2d[i++] = (byte) 42;//r + data2d[i++] = (byte) 42;//g + data2d[i++] = (byte) 42;//b + } + + this.data2D = ByteBuffer.wrap(data2d); + } + + + } + + private int getBlockState(int x, int y, int z) { + + if (!mNotFailed) return 0; + + //The codeOffset'th BlockState is wanted. + int codeOffset = getOffset(x, y, z); + + //How much BlockStates can one int32 hold? + int intCapa = 32 / blockCodeLenth; + + //The int32 that holds the wanted BlockState. + int stick = mainStorage.get(codeOffset / intCapa); + + //Get the BlockState. It's also the index in palette array. + int ind = (stick >> (codeOffset % intCapa * blockCodeLenth)) & msk[blockCodeLenth - 1]; + + //Transform the local BlockState into global id<<8|data structure. + return palette.get(ind); + } + + + @Override + public byte getBlockTypeId(int x, int y, int z) { + if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { + return 0; + } + return (byte) (getBlockState(x, y, z) >>> 8); + } + + @Override + public byte getBlockData(int x, int y, int z) { + if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { + return 0; + } + return (byte) (getBlockState(x, y, z) & 0xf); + } + + @Override + public byte getSkyLightValue(int x, int y, int z) { + if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { + return 0; + } + return 0; + } + + @Override + public byte getBlockLightValue(int x, int y, int z) { + //oldBlock light is not stored anymore + return 0; + } + + @Override + public boolean supportsBlockLightValues() { + return false; + } + + */ +/** + * Sets a oldBlock type, and also set the corresponding dirty table entry and set the saving flag. + *//* + + @Override + public void setBlockTypeId(int x, int y, int z, int type) { + if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { + return; + } + } + + @Override + public void setBlockData(int x, int y, int z, int newData) { + if (x >= chunkW || y >= chunkH || z >= chunkL || x < 0 || y < 0 || z < 0) { + return; + } + } + + private int getOffset(int x, int y, int z) { + return (((x << 4) | z) << 4) | y; + } + + @Override + public byte getBiome(int x, int z) { + return data2D.get(POS_BIOME_DATA + get2Di(x, z)); + } + + @Override + public byte getGrassR(int x, int z) { + Biome biome = Biome.getBiome(getBiome(x, z) & 0xff); + int res = getNoise(30 + (biome.color.red / 5), x, z); + return (byte) (res > 0xff ? 0xff : (res < 0 ? 0 : res)); + } + + @Override + public byte getGrassG(int x, int z) { + Biome biome = Biome.getBiome(getBiome(x, z) & 0xff); + int res = getNoise(120 + (biome.color.green / 5), x, z); + return (byte) (res > 0xff ? 0xff : (res < 0 ? 0 : res)); + } + + @Override + public byte getGrassB(int x, int z) { + Biome biome = Biome.getBiome(getBiome(x, z) & 0xff); + int res = getNoise(30 + (biome.color.blue / 5), x, z); + return (byte) (res > 0xff ? 0xff : (res < 0 ? 0 : res)); + } + + private int get2Di(int x, int z) { + return z * chunkL + x; + } + + @Override + public int getHeightMapValue(int x, int z) { + short h = data2D.getShort(POS_HEIGHTMAP + (get2Di(x, z) << 1)); + return ((h & 0xff) << 8) | ((h >> 8) & 0xff);//little endian to big endian + } +} +*/ diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1d2d13TerrainSubChunk.java b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1d2d13TerrainSubChunk.java new file mode 100644 index 00000000..b5c69f3f --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/chunk/terrain/V1d2d13TerrainSubChunk.java @@ -0,0 +1,427 @@ +package com.mithrilmania.blocktopograph.chunk.terrain; + +import android.util.Pair; + +import androidx.annotation.NonNull; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Streams; +import com.mithrilmania.blocktopograph.BuildConfig; +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.Block; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.BlockType; +import com.mithrilmania.blocktopograph.block.blockproperty.BlockProperty; +import com.mithrilmania.blocktopograph.chunk.ChunkTag; +import com.mithrilmania.blocktopograph.map.Dimension; +import com.mithrilmania.blocktopograph.nbt.convert.NBTInputStream; +import com.mithrilmania.blocktopograph.nbt.convert.NBTOutputStream; +import com.mithrilmania.blocktopograph.nbt.tags.ByteTag; +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.IntTag; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; +import com.mithrilmania.blocktopograph.util.LittleEndianOutputStream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public final class V1d2d13TerrainSubChunk extends TerrainSubChunk { + + private boolean mIsDualStorageSupported; + + // Masks used to extract BlockState bits of a certain oldBlock out of a int32, and vice-versa. + private static final int[] msk = {0b1, 0b11, 0b111, 0b1111, 0b11111, 0b111111, 0b1111111, + 0b11111111, + 0b111111111, 0b1111111111, 0b11111111111, + 0b111111111111, + 0b1111111111111, 0b11111111111111, 0b11111111111111}; + // There could be multiple BlockStorage let's read the first two. + private final BlockStorage[] mStorages; + + V1d2d13TerrainSubChunk() { + mStorages = new BlockStorage[2]; + mIsDualStorageSupported = true; + createEmptyBlockStorage(0); + } + + V1d2d13TerrainSubChunk(@NonNull ByteBuffer raw) { + + raw.order(ByteOrder.LITTLE_ENDIAN); + mStorages = new BlockStorage[2]; + + // The first byte indicates version. + switch (raw.get(0)) { + // 1: Only one BlockStorage starting from the next byte. + case 1: + mIsDualStorageSupported = false; + raw.position(1); + try { + mStorages[0] = BlockStorage.loadAndMoveForward(raw); + } catch (IOException e) { + if (BuildConfig.DEBUG) { + Log.d(this, e); + } + mIsError = true; + } + break; + // 8: One or more BlockStorage's, next byte is the count. + case 8: + mIsDualStorageSupported = true; + raw.position(1); + int count = raw.get(); + if (count < 1) { + mIsError = true; + return; + } + try { + mStorages[0] = BlockStorage.loadAndMoveForward(raw); + if (count > 1) mStorages[1] = BlockStorage.loadAndMoveForward(raw); + } catch (IOException e) { + if (BuildConfig.DEBUG) { + Log.d(this, e); + } + mIsError = true; + } + break; + default: + mIsError = true; + return; + } + mHasBlockLight = false; + mHasSkyLight = false; + } + + @NonNull + @Override + public BlockTemplate getBlockTemplate(int x, int y, int z, int layer) { + if (mIsError) return BlockTemplates.getAirTemplate(); + BlockStorage storage = mStorages[layer]; + if (storage == null) return BlockTemplates.getAirTemplate(); + return storage.getBlock(x, y, z).second; + } + + @NonNull + @Override + public Block getBlock(int x, int y, int z, int layer) { + if (mIsError) throw new RuntimeException(); + BlockStorage storage = mStorages[layer]; + if (storage == null) return BlockTemplates.getAirTemplate().getBlock(); + return storage.getBlock(x, y, z).first; + } + + @Override + public void setBlock(int x, int y, int z, int layer, @NonNull Block block) { + + // Has error or not supported. + if (mIsError || (layer > 0 && !mIsDualStorageSupported)) throw new RuntimeException(); + + BlockStorage storage = mStorages[layer]; + // Main storage won't be null unless error. + if (storage == null) storage = createEmptyBlockStorage(layer); + + // If space is enough. + if (storage.setBlockIfSpace(x, y, z, block)) return; + + // Or we have to extend the whole storage. + storage = BlockStorage.extend(storage); + + mStorages[layer] = storage; + storage.setBlockIfSpace(x, y, z, block); + } + + @Override + public int getBlockLightValue(int x, int y, int z) { + return 0; + } + + @Override + public int getSkyLightValue(int x, int y, int z) { + return 0; + } + + private BlockStorage createEmptyBlockStorage(int which) { + BlockStorage storage = BlockStorage.createNew(); + mStorages[which] = storage; + return storage; + } + + @Override + public void save(WorldData worldData, int chunkX, int chunkZ, Dimension dimension, int which) throws WorldData.WorldDBException, IOException { + + if (mIsError) return; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + LittleEndianOutputStream leos = new LittleEndianOutputStream(baos); + + int storageCount = mIsDualStorageSupported ? (mStorages[1] == null ? 1 : 2) : 1; + + if (mIsDualStorageSupported) { + leos.write(8); + leos.write(storageCount); + mStorages[0].write(leos); + if (storageCount == 2) mStorages[1].write(leos); + } else { + leos.write(1); + mStorages[0].write(leos); + } + leos.flush(); + + byte[] arr = baos.toByteArray(); + worldData.writeChunkData(chunkX, chunkZ, ChunkTag.TERRAIN, dimension, (byte) which, true, arr); + + } + + private static class BlockStorage { + + public static final String PALETTE_KEY_ROOT = ""; + public static final String PALETTE_KEY_NAME = "name"; + public static final String PALETTE_KEY_STATES = "states"; + public static final String PALETTE_KEY_VERSION = "version"; + + private final byte[] raw; + + // records is a view into raw + private final IntBuffer records; + + private final List palette; + + private final List renderPalette; + + private final int blockCodeLenth; + + private BlockStorage() { + raw = new byte[512]; + ByteBuffer bbuff = ByteBuffer.wrap(raw); + bbuff.order(ByteOrder.LITTLE_ENDIAN); + records = bbuff.asIntBuffer(); + + palette = new ArrayList<>(4); + renderPalette = new ArrayList<>(4); + var airTemplate = BlockTemplates.getAirTemplate(); + renderPalette.add(airTemplate); + palette.add(airTemplate.getBlock()); + + blockCodeLenth = 1; + } + + // stateful! wrapping with static creation method + private BlockStorage(@NonNull ByteBuffer buffer) throws IOException { + + //Read BlockState length. + //this byte = (length << 2) | serializedType. + blockCodeLenth = (buffer.get() & 0xff) >> 1; + + if (blockCodeLenth > 16) throw new IOException("mBlockLength > 16"); + + //We use this much of bytes to store BlockStates. + int bufsize = (4095 / (32 / blockCodeLenth) + 1) << 2; + byte[] arr = new byte[bufsize]; + ByteBuffer byteBuffer = ByteBuffer.wrap(arr); + byteBuffer.order(ByteOrder.LITTLE_ENDIAN); + records = byteBuffer.asIntBuffer(); + raw = arr; + + //No convenient way copy these stuff. + byteBuffer.put(buffer.array(), buffer.position(), bufsize); + buffer.position(buffer.position() + bufsize); + + //Palette items count. + int psize = buffer.getInt(); + +// if(psize>(1< most possible bound"); +// } + + //Construct the palette. Each item is a piece of nbt data. + palette = new ArrayList<>(16); + renderPalette = new ArrayList<>(16); + + //NBT reader requires a stream. + var bais = new ByteArrayInputStream(buffer.array()); + + // Skip for byte array would not fail. + //noinspection ResultOfMethodCallIgnored + bais.skip(buffer.position()); + + //Wrap it. + var nis = new NBTInputStream(bais, false); + for (int i = 0; i < psize; i++) + //Read a piece of nbt data, represented by a root CompoundTag. + addToPalette(deserializeBlock((CompoundTag) nis.readTag())); + + //If one day we need to read more BlockStorage's, this line helps. + buffer.position(buffer.position() + nis.getReadCount()); + } + + private BlockStorage(@NonNull BlockStorage old) { + blockCodeLenth = old.blockCodeLenth + 1; + palette = new ArrayList<>(old.palette); + renderPalette = new ArrayList<>(old.renderPalette); + int capa_new = 32 / blockCodeLenth; + int capa_old = 32 / old.blockCodeLenth; + int stick = 4095 / capa_new + 1; + byte[] newRecs = new byte[stick << 2]; + ByteBuffer newBb = ByteBuffer.wrap(newRecs); + newBb.order(ByteOrder.LITTLE_ENDIAN); + records = newBb.asIntBuffer(); + raw = newRecs; + for (int i = 0, hold = 0, hnew = 0, mold = 0, mnew = 0; i < 4096; i++) { + int idold = + (old.records.get(hold) >> (mold * old.blockCodeLenth)) & msk[old.blockCodeLenth - 1]; + idold <<= mnew * blockCodeLenth; + records.put(hnew, records.get(hnew) | idold); + mold++; + mnew++; + if (mold == capa_old) { + mold = 0; + hold++; + } + if (mnew == capa_new) { + mnew = 0; + hnew++; + } + } + } + + public static BlockStorage createNew() { + return new BlockStorage(); + } + + public static BlockStorage loadAndMoveForward(@NonNull ByteBuffer buffer) throws IOException { + return new BlockStorage(buffer); + } + + public static BlockStorage extend(@NonNull BlockStorage storage) { + return new BlockStorage(storage); + } + + private void addToPalette(Block block) { + palette.add(block); + renderPalette.add(BlockTemplates.getBest(block)); + } + + public boolean setBlockIfSpace( + int x, int y, int z, @NonNull Block block) { + int code = -1; + + // If in palette. + for (int localId = 0, paletteSize = palette.size(); localId < paletteSize; localId++) { + Block blockInPalette = palette.get(localId); + if (block.equals(blockInPalette)) { + code = localId; + break; + } + } + + // Or not. + if (code < 0) { + // Reached size limit. + int max = 1 << blockCodeLenth; + int size = palette.size(); + if (size >= max) return false; + + addToPalette(block); + code = size; + } + + // The codeOffset'th BlockState is wanted. + int codeOffset = getOffset(x, y, z); + + // How much BlockStates can one int32 hold? + int intCapa = 32 / blockCodeLenth; + + // The int32 that holds the wanted BlockState. + int whichInt = codeOffset / intCapa; + int stick = records.get(whichInt); + int shift = codeOffset % intCapa * blockCodeLenth; + stick &= ~(msk[blockCodeLenth - 1] << shift); + stick |= code << shift; + records.put(whichInt, stick); + + return true; + } + + public Pair getBlock(int x, int y, int z) { + + //The codeOffset'th BlockState is wanted. + int codeOffset = getOffset(x, y, z); + + //How much BlockStates can one int32 hold? + int intCapa = 32 / blockCodeLenth; + + //The int32 that holds the wanted BlockState. + int stick = records.get(codeOffset / intCapa); + + //Get the BlockState. It's also the index in palette array. + int ind = (stick >> (codeOffset % intCapa * blockCodeLenth)) & msk[blockCodeLenth - 1]; + + //Transform the local BlockState into global id<<8|data structure. + return new Pair<>(palette.get(ind), renderPalette.get(ind)); + } + + private void write(@NonNull LittleEndianOutputStream stream) throws IOException { + + // Code length. + stream.write(blockCodeLenth << 1); + + // Int32s. + stream.write(raw); + + // Palette size. + int size = palette.size(); + stream.writeInt(size); + + // Palettes. + NBTOutputStream nos = new NBTOutputStream(stream, false, true); + + for (int j = 0; j < size; j++) + nos.writeTag(serializeBlock(palette.get(j))); + } + + private static CompoundTag serializeBlock(@NonNull Block block) { + return new CompoundTag(PALETTE_KEY_ROOT, Lists.newArrayList( + new StringTag(PALETTE_KEY_NAME, block.getName()), + new CompoundTag(PALETTE_KEY_STATES, new ArrayList<>(Streams.concat(Streams.zip( + Arrays.stream(block.getType().getKnownProperties()).map(BlockProperty::getName), + Arrays.stream(block.getKnownProperties()), Maps::immutableEntry).filter(Objects::nonNull), + block.getCustomProperties().entrySet().stream()).map( + (entry) -> { + var name = entry.getKey(); + var val = entry.getValue(); + if (val instanceof Byte) return new ByteTag(name, (Byte) val); + else if (val instanceof Integer) + return new IntTag(name, (Integer) val); + else if (val instanceof String) + return new StringTag(name, (String) val); + else + throw new RuntimeException("block state with unsupported type"); + }).collect(Collectors.toList()))), + new IntTag(PALETTE_KEY_VERSION, 2012) + )); + } + + private static Block deserializeBlock(@NonNull CompoundTag tag) { + var name = ((StringTag) tag.getChildTagByKey(PALETTE_KEY_NAME)).getValue(); + var blockType = BlockType.get(name); + var builder = (blockType == null ? new Block.Builder(name) : new Block.Builder(blockType)); + for (var state : ((CompoundTag) tag.getChildTagByKey(PALETTE_KEY_STATES)).getValue()) + builder.setProperty(state); + Log.d(BlockStorage.class, "fuckfuckversion" + tag.getChildTagByKey(PALETTE_KEY_VERSION).getValue()); + return builder.build(); + } + + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/flat/EditFlatFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/flat/EditFlatFragment.java new file mode 100644 index 00000000..96d1e068 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/flat/EditFlatFragment.java @@ -0,0 +1,261 @@ +package com.mithrilmania.blocktopograph.flat; + +import android.app.Activity; +import android.content.Intent; +import android.content.res.AssetManager; +import android.os.AsyncTask; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.google.android.material.snackbar.Snackbar; +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.ListingBlock; +import com.mithrilmania.blocktopograph.databinding.FragLayersBinding; +import com.mithrilmania.blocktopograph.databinding.ItemWorldLayerBinding; +import com.mithrilmania.blocktopograph.util.UiUtil; +import com.woxthebox.draglistview.DragItemAdapter; +import com.woxthebox.draglistview.DragListView; +import com.woxthebox.draglistview.swipe.ListSwipeHelper; +import com.woxthebox.draglistview.swipe.ListSwipeItem; + +import java.io.Serializable; +import java.lang.ref.WeakReference; +import java.util.LinkedList; +import java.util.List; + +public final class EditFlatFragment extends Fragment { + + static final String EXTRA_KEY_LIST_INDEX = "index"; + static final String EXTRA_KEY_LIST_IS_ADD = "isAdd"; + static final String EXTRA_KEY_LIST_LAYER = "layer"; + static final String EXTRA_KEY_LIST_EXISTING_SUM = "existingSum"; + private static final int REQUEST_CODE_EDIT_LAYER = 2013; + private FragLayersBinding mBinding; + private MeowAdapter mMeowAdapter; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate(inflater, R.layout.frag_layers, container, false); + new LoadTask(this).execute(); + return mBinding.getRoot(); + } + + private void onClickAddOrEditLayer(int index, Layer layer, boolean isAdd, int existingSum) { + Activity activity = getActivity(); + if (activity == null) return; + startActivityForResult( + new Intent(activity, EditLayerDialog.class) + .putExtra(EXTRA_KEY_LIST_INDEX, index) + .putExtra(EXTRA_KEY_LIST_LAYER, layer) + .putExtra(EXTRA_KEY_LIST_IS_ADD, isAdd) + .putExtra(EXTRA_KEY_LIST_EXISTING_SUM, existingSum), + REQUEST_CODE_EDIT_LAYER + ); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_CODE_EDIT_LAYER) { + if (resultCode != Activity.RESULT_OK) return; + int index = data.getIntExtra(EXTRA_KEY_LIST_INDEX, 0); + Serializable ser = data.getSerializableExtra(EXTRA_KEY_LIST_LAYER); + Layer layer = (Layer) ser; + if (data.getBooleanExtra(EXTRA_KEY_LIST_IS_ADD, true)) { + mMeowAdapter.insert(index + 1, layer); + } else { + mMeowAdapter.change(index, layer); + } + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + public List getResultLayers() { + return mMeowAdapter.getItemList(); + } + + private static class LoadTask extends AsyncTask { + + private final WeakReference thiz; + private AlertDialog mWaitDialog; + + private LoadTask(EditFlatFragment thiz) { + this.thiz = new WeakReference<>(thiz); + } + + @Override + protected void onPreExecute() { + Activity activity = thiz.get().getActivity(); + if (activity == null) return; + mWaitDialog = UiUtil.buildProgressWaitDialog(activity, 0, null); + mWaitDialog.show(); + } + + @Override + protected Void doInBackground(Void... voids) { + try { + Activity activity = thiz.get().getActivity(); + if (activity == null) return null; + ListingBlock.B_1_STONE.getIcon(activity.getAssets()); + } catch (Exception e) { + Log.d(this, e); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + EditFlatFragment thiz = this.thiz.get(); + //If the activity quit nothing needs to be done. + if (thiz == null) return; + try { + DragListView listView = thiz.mBinding.list; + thiz.mMeowAdapter = thiz.new MeowAdapter(thiz.getResources().getAssets()); + listView.setLayoutManager(new LinearLayoutManager(thiz.getActivity())); + listView.setCanDragHorizontally(false); + listView.setAdapter(thiz.mMeowAdapter, false); + listView.setSwipeListener(thiz.mMeowAdapter); + thiz.mMeowAdapter.loadDefault(); + } catch (Exception e) { + Log.d(this, e); + Activity activity = thiz.getActivity(); + if (activity != null) UiUtil.toastError(activity); + } + mWaitDialog.dismiss(); + } + } + + private class MeowAdapter extends DragItemAdapter implements ListSwipeHelper.OnSwipeListener { + + @NonNull + private AssetManager assMan; + + MeowAdapter(@NonNull AssetManager assMan) { + setItemList(new LinkedList<>()); + this.assMan = assMan; + } + + @Override + public long getUniqueItemId(int i) { + Layer layer = mItemList.get(i); + //return (((long) i) << 32) | (layer.block.id << 16) | (layer.block.subId << 8) | layer.amount; + return layer.uid; + } + + void loadDefault() { + Layer layer = new Layer(BlockTemplates.getOfType("minecraft:bedrock")[0], 1); + addItem(0, layer); + layer = new Layer(BlockTemplates.getOfType("minecraft:dirt")[0], 29); + addItem(0, layer); + layer = new Layer(BlockTemplates.getOfType("minecraft:grass")[0], 1); + addItem(0, layer); + layer = new Layer(BlockTemplates.getOfType("minecraft:tallgrass")[0],1); + addItem(0, layer); + } + + void insert(int index, Layer layer) { + mItemList.add(index, layer); + notifyItemInserted(index); + } + + void change(int index, Layer layer) { + mItemList.set(index, layer); + notifyItemChanged(index, layer); + } + + @NonNull + @Override + public MeowHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int in) { + ItemWorldLayerBinding binding = DataBindingUtil.inflate( + getLayoutInflater(), R.layout.item_world_layer, mBinding.list, false); + MeowHolder holder = new MeowHolder(binding); + holder.binding.add.setOnClickListener(view -> { + int sum = 0;//Existing height. Total height shall be less then 128 we need to ensure. + for (Layer l : mItemList) { + sum += l.amount; + } + onClickAddOrEditLayer(holder.getLayoutPosition(), new Layer(), true, sum); + }); + holder.binding.root.setOnClickListener(view -> { + int index = holder.getLayoutPosition(); + int sum = 0;//Existing height. Total height shall be less then 128 we need to ensure. + for (int i = 0, mItemListSize = mItemList.size(); i < mItemListSize; i++) { + if (i == index) continue; + Layer l = mItemList.get(i); + sum += l.amount; + } + onClickAddOrEditLayer(index, mItemList.get(index), false, sum); + }); + holder.binding.root.setTag(new WeakReference<>(holder)); + return holder; + } + + @Override + public void onBindViewHolder(@NonNull MeowHolder holder, int position) { + super.onBindViewHolder(holder, position); + Layer layer = mItemList.get(position); + holder.binding.setLayer(layer); + holder.binding.icon.setImageBitmap(layer.block.getIcon().getIcon(getContext())); + } + + @Override + public void onItemSwipeStarted(ListSwipeItem item) { + } + + @Nullable + private MeowHolder getHolderFromTag(@NonNull ListSwipeItem view) { + Object tag = view.getTag(); + if (!(tag instanceof WeakReference)) return null; + WeakReference ref = (WeakReference) tag; + Object mho = ref.get(); + return (MeowHolder) mho; + } + + @Override + public void onItemSwipeEnded(ListSwipeItem item, ListSwipeItem.SwipeDirection swipedDirection) { + if (swipedDirection != ListSwipeItem.SwipeDirection.LEFT) return; + MeowHolder mh = getHolderFromTag(item); + if (mh == null) return; + int position = mh.getAdapterPosition(); + int size = mItemList.size(); + if (size > 1) { + mItemList.remove(position); + notifyItemRemoved(position); + } else if (size == 1) { + mItemList.set(0, new Layer()); + Snackbar.make(mBinding.list, R.string.edit_flat_atleast, Snackbar.LENGTH_SHORT).show(); + notifyItemChanged(0); + } + } + + @Override + public void onItemSwiping(ListSwipeItem item, float swipedDistanceX) { + float alpha = -swipedDistanceX / item.getMeasuredWidth() * 1.2f; + MeowHolder mh = getHolderFromTag(item); + if (mh == null) return; + mh.binding.itemRight.setAlpha(alpha); + } + + private class MeowHolder extends DragItemAdapter.ViewHolder { + + ItemWorldLayerBinding binding; + + MeowHolder(@NonNull ItemWorldLayerBinding binding) { + super(binding.getRoot(), R.id.icon, false); + this.binding = binding; + binding.root.setSupportedSwipeDirection(ListSwipeItem.SwipeDirection.LEFT); + } + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/flat/EditLayerDialog.java b/app/src/main/java/com/mithrilmania/blocktopograph/flat/EditLayerDialog.java new file mode 100644 index 00000000..25f75a87 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/flat/EditLayerDialog.java @@ -0,0 +1,148 @@ +package com.mithrilmania.blocktopograph.flat; + +import android.content.Intent; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.EditText; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.databinding.DataBindingUtil; + +import com.andreabaccega.formedittextvalidator.Validator; +import com.andreabaccega.widget.FormEditText; +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.ListingBlock; +import com.mithrilmania.blocktopograph.databinding.DialogEditLayerBinding; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.io.Serializable; + +import static com.mithrilmania.blocktopograph.flat.EditFlatFragment.EXTRA_KEY_LIST_EXISTING_SUM; +import static com.mithrilmania.blocktopograph.flat.EditFlatFragment.EXTRA_KEY_LIST_INDEX; +import static com.mithrilmania.blocktopograph.flat.EditFlatFragment.EXTRA_KEY_LIST_IS_ADD; +import static com.mithrilmania.blocktopograph.flat.EditFlatFragment.EXTRA_KEY_LIST_LAYER; + +public final class EditLayerDialog extends AppCompatActivity { + + public static final int REQUEST_CODE_PICK_BLOCK = 2014; + private boolean mIsAdd; + private int mExistingSum; + private int mPositon; + private DialogEditLayerBinding mBinding; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this, R.layout.dialog_edit_layer); + setResult(RESULT_CANCELED); + + Intent intent = getIntent(); + if (savedInstanceState != null || intent == null) { + //The activity does not do anything worth restore. + finish(); + return; + } + Serializable ser = intent.getSerializableExtra(EXTRA_KEY_LIST_LAYER); + if (!(ser instanceof Layer)) { + Log.d(this, "wtf?"); + finish(); + return; + } + Layer layer = (Layer) ser; + + mPositon = intent.getIntExtra(EXTRA_KEY_LIST_INDEX, -1); + mBinding.setLayer(layer); + mIsAdd = intent.getBooleanExtra(EXTRA_KEY_LIST_IS_ADD, true); + mExistingSum = intent.getIntExtra(EXTRA_KEY_LIST_EXISTING_SUM, 0); + + if (mIsAdd) setTitle(R.string.edit_flat_add_layer_title); + else setTitle(R.string.edit_flat_edit_layer_title); + + FormEditText amountBar = mBinding.amount; + amountBar.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + mBinding.amount.testValidity(); + } + }); + amountBar.addValidator(new AmountValidator(getString(R.string.edit_layer_amount_constrait))); + + mBinding.icon.setImageBitmap(layer.block.getIcon().getIcon(this)); + UiUtil.blendBlockColor(mBinding.frame, layer.block); + } + + public void onClickChangeBlock(View view) { + startActivityForResult( + new Intent(this, PickBlockActivity.class), REQUEST_CODE_PICK_BLOCK + ); + } + + public void onClickPositiveButton(View view) { + Layer layer = mBinding.getLayer(); + String am = mBinding.amount.getText().toString(); + int ami = 1; + if (!am.isEmpty()) try { + ami = Integer.parseInt(am); + } catch (NumberFormatException e) { + // + } + layer.amount = ami; + setResult(RESULT_OK, new Intent() + .putExtra(EXTRA_KEY_LIST_INDEX, mPositon) + .putExtra(EXTRA_KEY_LIST_IS_ADD, mIsAdd) + .putExtra(EXTRA_KEY_LIST_LAYER, layer)); + finish(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + switch (requestCode) { + case REQUEST_CODE_PICK_BLOCK: { + if (resultCode != RESULT_OK) return; + assert data != null; + BlockTemplate block = (BlockTemplate) data.getSerializableExtra(PickBlockActivity.EXTRA_KEY_BLOCK); + Layer layer = mBinding.getLayer(); + layer.block = block; + mBinding.setLayer(layer); + mBinding.icon.setImageBitmap(layer.block.getIcon().getIcon(this)); + UiUtil.blendBlockColor(mBinding.frame, block); + //mBinding.notifyChange(); + return; + } + } + super.onActivityResult(requestCode, resultCode, data); + } + + public class AmountValidator extends Validator { + + AmountValidator(String customErrorMessage) { + super(customErrorMessage); + } + + @Override + public boolean isValid(EditText et) { + String text = et.getText().toString(); + if (text.isEmpty()) return true; + int val; + try { + val = Integer.parseInt(text); + } catch (NumberFormatException e) { + return false; + } + return val >= 0 && val < 128 - mExistingSum; + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/flat/FlatLayers.java b/app/src/main/java/com/mithrilmania/blocktopograph/flat/FlatLayers.java new file mode 100644 index 00000000..e5522c7e --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/flat/FlatLayers.java @@ -0,0 +1,113 @@ +package com.mithrilmania.blocktopograph.flat; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public final class FlatLayers { + + private static final String KEY_BIOME_ID = "biome_id"; + private static final String KEY_BLOCK_LAYERS = "block_layers"; + private static final String KEY_BLOCK_NAME = "block_name"; + private static final String KEY_BLOCK_DATA = "block_data"; + private static final String KEY_COUNT = "count"; + private static final String KEY_VERSION = "encoding_version"; + private static final String KEY_STRUCTURE_OPS = "structure_options"; + + private boolean hasStructureOps; + private int biomeId; + private int encodingVersion; + private Layer[] mLayers; + + @Nullable + public static FlatLayers parse(String json) { + try { + JSONObject root = new JSONObject(json); + FlatLayers layers = new FlatLayers(); + layers.biomeId = root.getInt(KEY_BIOME_ID); + layers.encodingVersion = root.getInt(KEY_VERSION); + JSONArray jlayers = root.getJSONArray(KEY_BLOCK_LAYERS); + Layer[] alayers = new Layer[jlayers.length()]; + for (int i = 0; i < alayers.length; i++) { + JSONObject jlayer = jlayers.getJSONObject(i); + String name = jlayer.getString(KEY_BLOCK_NAME); + int id = KnownBlockRepr.resolve(name); + int data = jlayer.getInt(KEY_BLOCK_DATA); + int count = jlayer.getInt(KEY_COUNT); + KnownBlockRepr block = KnownBlockRepr.getBestBlock(id, data); + //alayers[i] = new Layer(block, count); + } + layers.hasStructureOps = root.has(KEY_STRUCTURE_OPS); + return layers; + } catch (JSONException e) { + Log.d(FlatLayers.class, e); + } + return null; + } + + @NonNull + public static FlatLayers createNew(int biomeId, Layer[] layers) { + FlatLayers ret = new FlatLayers(); + ret.biomeId = biomeId; + ret.encodingVersion = 4; + ret.mLayers = layers; + return ret; + } + + private FlatLayers() { + } + + public int getBiomeId() { + return biomeId; + } + + public void setBiomeId(int biomeId) { + this.biomeId = biomeId; + } + + public int getEncodingVersion() { + return encodingVersion; + } + + public void setEncodingVersion(int encodingVersion) { + this.encodingVersion = encodingVersion; + } + + public Layer[] getmLayers() { + return mLayers; + } + + public void setmLayers(Layer[] mLayers) { + this.mLayers = mLayers; + } + + @Nullable + public String write() { + try { + JSONObject root = new JSONObject(); + root.put(KEY_BIOME_ID, biomeId); + root.put(KEY_VERSION, encodingVersion); + JSONArray jlayers = new JSONArray(); + for (Layer layer : mLayers) { + JSONObject jlayer = new JSONObject(); + jlayer.put(KEY_BLOCK_NAME, layer.block.getBlock().getName()); + //jlayer.put(KEY_BLOCK_DATA, layer.block.subId); + jlayer.put(KEY_COUNT, layer.amount); + jlayers.put(jlayer); + } + root.put(KEY_BLOCK_LAYERS, jlayers); + if (hasStructureOps) root.put(KEY_STRUCTURE_OPS, null); + return root.toString(4); + } catch (JSONException e) { + Log.d(FlatLayers.class, e); + } + return null; + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/flat/Layer.java b/app/src/main/java/com/mithrilmania/blocktopograph/flat/Layer.java new file mode 100644 index 00000000..ab188d18 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/flat/Layer.java @@ -0,0 +1,46 @@ +package com.mithrilmania.blocktopograph.flat; + +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.ListingBlock; + +import java.io.Serializable; + +public final class Layer implements Serializable { + + private static long counter = 0; + public BlockTemplate block; + public int amount; + public long uid; + + private synchronized void genUid() { + // What the hell are you doing? + // Well calm down my friend.... + // Nothing serious, right? + // ... + uid = counter;//System.currentTimeMillis(); + counter++; + } + + public Layer() { + block = BlockTemplates.getOfType("minecraft:air")[0]; + amount = 1; + genUid(); + } + + Layer(BlockTemplate block, int amount) { + this.block = block; + this.amount = amount; + genUid(); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (!(obj instanceof Layer)) return false; + Layer another = (Layer) obj; + if (amount != another.amount) return false; + return block == another.block; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/flat/PickBlockActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/flat/PickBlockActivity.java new file mode 100644 index 00000000..c6ee2419 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/flat/PickBlockActivity.java @@ -0,0 +1,196 @@ +package com.mithrilmania.blocktopograph.flat; + +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.common.collect.Streams; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.databinding.DialogPickBlockBinding; +import com.mithrilmania.blocktopograph.databinding.ItemPickBlockBinding; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public final class PickBlockActivity extends AppCompatActivity { + + public static final String EXTRA_KEY_BLOCK = "block"; + private DialogPickBlockBinding mBinding; + private LinearLayoutManager mListManager; + private MeowAdapter mAdapter; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this, R.layout.dialog_pick_block); + + RecyclerView list = mBinding.list; + mListManager = new LinearLayoutManager(this); + list.setLayoutManager(mListManager); + mAdapter = new MeowAdapter(); + list.setAdapter(mAdapter); + setResult(RESULT_CANCELED); + + mBinding.text.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + new UpdateListTask(PickBlockActivity.this).execute(); + } + }); + + new UpdateListTask(PickBlockActivity.this).execute(); + } + + private static class UpdateListTask extends AsyncTask { + + private final WeakReference thiz; + private String keyword; + private int index1, index2; + + private UpdateListTask(PickBlockActivity thiz) { + this.thiz = new WeakReference<>(thiz); + } + + @Override + protected void onPreExecute() { + PickBlockActivity activity = thiz.get(); + if (activity == null) return; + keyword = activity.mBinding.text.getText().toString(); + + //Save for restoring. + index1 = activity.mListManager.findFirstVisibleItemPosition(); + index2 = activity.mListManager.findLastVisibleItemPosition(); + if (index2 <= index1) index2 = index1; + } + + @Override + protected Void doInBackground(Void... voids) { + PickBlockActivity activity = thiz.get(); + if (activity == null) return null; + List list = activity.mAdapter.getListControl(); + + //Backup all candidates. + BlockTemplate[] olds = null; + if (index1 >= 0) { + olds = new BlockTemplate[index2 - index1 + 1]; + for (int i = index1, limit = list.size(); i < olds.length && i < limit; i++) { + olds[i] = list.get(i); + } + } + //Reset. + list.clear(); + + //Restore. + String text = keyword; + int num; + try { + num = Integer.parseInt(text); + } catch (NumberFormatException e) { + num = -1; + } + for (Iterator it = BlockTemplates.getAll().iterator(); it.hasNext(); ) { + BlockTemplate b = it.next(); + if ( + (b.getBlock().getName().contains(text))) + list.add(b); + } + int position = -1; + if (olds != null) for (BlockTemplate b : olds) { + int i = list.indexOf(b); + if (i != -1) { + position = i; + break; + } + } + index1 = position; + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + PickBlockActivity activity = thiz.get(); + if (activity == null) return; + activity.mAdapter.notifyDataSetChanged(); + if (index1 >= 0) activity.mListManager.scrollToPosition(index1); + } + } + + private class MeowAdapter extends RecyclerView.Adapter { + + private final List mBlocks; + + private MeowAdapter() { + mBlocks = new ArrayList<>(512); + } + + @NonNull + @Override + public MeowHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + ItemPickBlockBinding binding = DataBindingUtil.inflate( + getLayoutInflater(), R.layout.item_pick_block, mBinding.list, false); + View root = binding.getRoot(); + MeowHolder holder = new MeowHolder(root); + holder.binding = binding; + root.setOnClickListener(v -> { + //UiUtil.toast(PickBlockActivity.this,""+i); + setResult(RESULT_OK, new Intent() + .putExtra(EXTRA_KEY_BLOCK, holder.binding.getOldBlock()));//;(KnownBlockRepr) v.getTag())); + finish(); + }); + return holder; + } + + @Override + public void onBindViewHolder(@NonNull MeowHolder meowHolder, int i) { + BlockTemplate oldBlock = mBlocks.get(i); + ItemPickBlockBinding binding = meowHolder.binding; + binding.setOldBlock(oldBlock); + //binding.getRoot().setTag(oldBlock); + binding.icon.setImageBitmap(oldBlock.getIcon().getIcon(PickBlockActivity.this)); + UiUtil.blendBlockColor(binding.getRoot(), oldBlock); + } + + @Override + public int getItemCount() { + return mBlocks.size(); + } + + List getListControl() { + return mBlocks; + } + + class MeowHolder extends RecyclerView.ViewHolder { + + ItemPickBlockBinding binding; + + MeowHolder(@NonNull View itemView) { + super(itemView); + } + } + + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/Biome.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/Biome.java index 3eaedd81..41624d90 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/Biome.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/Biome.java @@ -2,134 +2,161 @@ import android.util.SparseArray; -import com.mithrilmania.blocktopograph.util.Color; +import com.mithrilmania.blocktopograph.util.ColorWrapper; + /* Biome enum for MCPE -- by @mithrilmania +Reference link: https://minecraft.fandom.com/wiki/Biome/ID --- Please attribute @mithrilmania for generating+updating this enum */ public enum Biome { - OCEAN(0, "Ocean", Color.fromRGB(2, 0, 112)), - PLAINS(1, "Plains", Color.fromRGB(140, 176, 96)), - DESERT(2, "Desert", Color.fromRGB(251, 148, 27)), - EXTREME_HILLS(3, "Extreme Hills", Color.fromRGB(93, 99, 93)), - FOREST(4, "Forest", Color.fromRGB(2, 99, 32)), - TAIGA(5, "Taiga", Color.fromRGB(9, 102, 91)), - SWAMPLAND(6, "Swampland", Color.fromRGB(4, 200, 139)), - RIVER(7, "River", Color.fromRGB(1, 1, 255)), - HELL(8, "Hell", Color.fromRGB(255, 0, 1)), - SKY(9, "Sky", Color.fromRGB(130, 129, 254)), - FROZEN_OCEAN(10, "Frozen Ocean", Color.fromRGB(142, 141, 161)), - FROZEN_RIVER(11, "Frozen River", Color.fromRGB(159, 163, 255)), - ICE_PLAINS(12, "Ice Plains", Color.fromRGB(255, 254, 255)), - ICE_MOUNTAINS(13, "Ice Mountains", Color.fromRGB(162, 157, 157)), - MUSHROOM_ISLAND(14, "Mushroom Island", Color.fromRGB(254, 1, 255)), - MUSHROOM_ISLAND_SHORE(15, "Mushroom Island Shore", Color.fromRGB(158, 3, 253)), - BEACH(16, "Beach", Color.fromRGB(250, 223, 85)), - DESERT_HILLS(17, "Desert Hills", Color.fromRGB(212, 94, 15)), - FOREST_HILLS(18, "Forest Hills", Color.fromRGB(37, 86, 30)), - TAIGA_HILLS(19, "Taiga Hills", Color.fromRGB(25, 54, 49)), - EXTREME_HILLS_EDGE(20, "Extreme Hills Edge", Color.fromRGB(115, 118, 157)), - JUNGLE(21, "Jungle", Color.fromRGB(82, 122, 7)), - JUNGLE_HILLS(22, "Jungle Hills", Color.fromRGB(46, 64, 3)), - JUNGLE_EDGE(23, "Jungle Edge", Color.fromRGB(99, 142, 24)), - DEEP_OCEAN(24, "Deep Ocean", Color.fromRGB(2, 0, 47)), - STONE_BEACH(25, "Stone Beach", Color.fromRGB(162, 164, 132)), - COLD_BEACH(26, "Cold Beach", Color.fromRGB(250, 238, 193)), - BIRCH_FOREST(27, "Birch Forest", Color.fromRGB(48, 117, 70)), - BIRCH_FOREST_HILLS(28, "Birch Forest Hills", Color.fromRGB(29, 94, 51)), - ROOFED_FOREST(29, "Roofed Forest", Color.fromRGB(66, 82, 24)), - COLD_TAIGA(30, "Cold Taiga", Color.fromRGB(49, 85, 75)), - COLD_TAIGA_HILLS(31, "Cold Taiga Hills", Color.fromRGB(34, 61, 52)), - MEGA_TAIGA(32, "Mega Taiga", Color.fromRGB(92, 105, 84)), - MEGA_TAIGA_HILLS(33, "Mega Taiga Hills", Color.fromRGB(70, 76, 59)), - EXTREME_HILLS_PLUS(34, "Extreme Hills+", Color.fromRGB(79, 111, 81)), - SAVANNA(35, "Savanna", Color.fromRGB(192, 180, 94)), - SAVANNA_PLATEAU(36, "Savanna Plateau", Color.fromRGB(168, 157, 98)), - MESA(37, "Mesa", Color.fromRGB(220, 66, 19)), - MESA_PLATEAU_F(38, "Mesa Plateau F", Color.fromRGB(174, 152, 100)), - MESA_PLATEAU(39, "Mesa Plateau", Color.fromRGB(202, 139, 98)), - - //fix the colors for these - SMALL_END_ISLANDS(40, "Small End Islands",Color.fromRGB(202, 139, 98)), - END_MIDLANDS(41, "End Midlands",Color.fromRGB(202, 139, 98)), - END_HIGHLANDS(42, "End Highlands",Color.fromRGB(202, 139, 98)), - END_BARRENS(43, "End Barrens",Color.fromRGB(202, 139, 98)), - WARM_OCEAN(44, "Warm Ocean",Color.fromRGB(202, 139, 98)), - LUKEWARM_OCEAN(45, "Lukewarm Ocean",Color.fromRGB(202, 139, 98)), - COLD_OCEAN(46, "Cold Ocean",Color.fromRGB(202, 139, 98)), - DEEP_WARM_OCEAN(47, "Deep Warm Ocean",Color.fromRGB(202, 139, 98)), - DEEP_LUKEWARM_OCEAN(48, "Deep Lukewarm Ocean",Color.fromRGB(202, 139, 98)), - DEEP_COLD_OCEAN(49, "Deep Cold Ocean",Color.fromRGB(202, 139, 98)), - DEEP_FROZEN_OCEAN(50, "Deep Frozen Ocean",Color.fromRGB(202, 139, 98)), - - //fix the colors for the void - THE_VOID(127, "The Void", Color.fromRGB(81, 79, 195)), - - OCEAN_M(128, "Ocean M", Color.fromRGB(81, 79, 195)), - SUNFLOWER_PLAINS(129, "Sunflower Plains", Color.fromRGB(220, 255, 177)), - DESERT_M(130, "Desert M", Color.fromRGB(255, 230, 101)), - EXTREME_HILLS_M(131, "Extreme Hills M", Color.fromRGB(177, 176, 174)), - FLOWER_FOREST(132, "Flower Forest", Color.fromRGB(82, 180, 110)), - TAIGA_M(133, "Taiga M", Color.fromRGB(90, 182, 171)), - SWAMPLAND_M(134, "Swampland M", Color.fromRGB(87, 255, 255)), - RIVER_M(135, "River M", Color.fromRGB(82, 79, 255)), - HELL_M(136, "Hell M", Color.fromRGB(255, 80, 83)), - SKY_M(137, "Sky M", Color.fromRGB(210, 211, 255)), - FROZEN_OCEAN_M(138, "Frozen Ocean M", Color.fromRGB(226, 224, 241)), - FROZEN_RIVER_M(139, "Frozen River M", Color.fromRGB(239, 242, 255)), - ICE_PLAINS_SPIKES(140, "Ice Plains Spikes", Color.fromRGB(223, 255, 255)), - ICE_MOUNTAINS_M(141, "Ice Mountains M", Color.fromRGB(237, 237, 238)), - MUSHROOM_ISLAND_M(142, "Mushroom Island M", Color.fromRGB(255, 82, 255)), - MUSHROOM_ISLAND_SHORE_M(143, "Mushroom Island Shore M", Color.fromRGB(243, 82, 255)), - BEACH_M(144, "Beach M", Color.fromRGB(255, 255, 162)), - DESERT_HILLS_M(145, "Desert Hills M", Color.fromRGB(255, 177, 100)), - FOREST_HILLS_M(146, "Forest Hills M", Color.fromRGB(113, 167, 109)), - TAIGA_HILLS_M(147, "Taiga Hills M", Color.fromRGB(103, 135, 134)), - EXTREME_HILLS_EDGE_M(148, "Extreme Hills Edge M", Color.fromRGB(196, 203, 234)), - JUNGLE_M(149, "Jungle M", Color.fromRGB(160, 203, 92)), - JUNGLE_HILLS_M(150, "Jungle Hills M", Color.fromRGB(127, 146, 86)), - JUNGLE_EDGE_M(151, "Jungle Edge M", Color.fromRGB(179, 217, 105)), - DEEP_OCEAN_M(152, "Deep Ocean M", Color.fromRGB(82, 79, 130)), - STONE_BEACH_M(153, "Stone Beach M", Color.fromRGB(242, 243, 209)), - COLD_BEACH_M(154, "Cold Beach M", Color.fromRGB(255, 255, 255)), - BIRCH_FOREST_M(155, "Birch Forest M", Color.fromRGB(131, 194, 148)), - BIRCH_FOREST_HILLS_M(156, "Birch Forest Hills M", Color.fromRGB(111, 175, 133)), - ROOFED_FOREST_M(157, "Roofed Forest M", Color.fromRGB(143, 158, 109)), - COLD_TAIGA_M(158, "Cold Taiga M", Color.fromRGB(132, 163, 156)), - COLD_TAIGA_HILLS_M(159, "Cold Taiga Hills M", Color.fromRGB(113, 143, 136)), - MEGA_SPRUCE_TAIGA(160, "Mega Spruce Taiga", Color.fromRGB(168, 180, 164)), - REDWOOD_TAIGA_HILLS_M(161, "Redwood Taiga Hills M", Color.fromRGB(150, 158, 140)), - EXTREME_HILLS_PLUS_M(162, "Extreme Hills+ M", Color.fromRGB(161, 194, 158)), - SAVANNA_M(163, "Savanna M", Color.fromRGB(255, 255, 173)), - SAVANNA_PLATEAU_M(164, "Savanna Plateau M", Color.fromRGB(247, 238, 180)), - MESA_BRYCE(165, "Mesa (Bryce)", Color.fromRGB(255, 151, 101)), - MESA_PLATEAU_F_M(166, "Mesa Plateau F M", Color.fromRGB(255, 234, 179)), - MESA_PLATEAU_M(167, "Mesa Plateau M", Color.fromRGB(255, 220, 184)), - BAMBOO_JUNGLE(168, "Bamboo Jungle", Color.fromRGB(255, 220, 184)), - BAMBOO_JUNGLE_HILLS(169, "Bamboo Jungle Hills", Color.fromRGB(255, 220, 184)); - - public final int id; - public final String name; - public final Color color; - - Biome(int id, String name, Color color){ - this.id = id; - this.name = name; - this.color = color; - } - - private static final SparseArray biomeMap; - static { - biomeMap = new SparseArray<>(); - for(Biome b : Biome.values()){ - biomeMap.put(b.id, b); - } - } - - public static Biome getBiome(int id){ - return biomeMap.get(id); - } + OCEAN(0, "Ocean", ColorWrapper.fromRGB(2, 0, 112)), + PLAINS(1, "Plains", ColorWrapper.fromRGB(140, 176, 96)), + DESERT(2, "Desert", ColorWrapper.fromRGB(251, 148, 27)), + EXTREME_HILLS(3, "Mountains", ColorWrapper.fromRGB(93, 99, 93)), + FOREST(4, "Forest", ColorWrapper.fromRGB(2, 99, 32)), + TAIGA(5, "Taiga", ColorWrapper.fromRGB(9, 102, 91)), + SWAMPLAND(6, "Swampland", ColorWrapper.fromRGB(4, 200, 139)), + RIVER(7, "River", ColorWrapper.fromRGB(1, 1, 255)), + HELL(8, "Nether Wastes", ColorWrapper.fromRGB(132, 65, 65)), + THE_END(9, "The End", ColorWrapper.fromRGB(130, 129, 254)), + FROZEN_OCEAN(10, "Frozen Ocean", ColorWrapper.fromRGB(142, 141, 161)), + FROZEN_RIVER(11, "Frozen River", ColorWrapper.fromRGB(159, 163, 255)), + ICE_PLAINS(12, "Ice Plains", ColorWrapper.fromRGB(255, 254, 255)), + ICE_MOUNTAINS(13, "Ice Mountains", ColorWrapper.fromRGB(162, 157, 157)), + MUSHROOM_ISLAND(14, "Mushroom Fields", ColorWrapper.fromRGB(254, 1, 255)), + MUSHROOM_ISLAND_SHORE(15, "Mushroom Fields Shore", ColorWrapper.fromRGB(158, 3, 253)), + BEACH(16, "Beach", ColorWrapper.fromRGB(250, 223, 85)), + DESERT_HILLS(17, "Desert Hills", ColorWrapper.fromRGB(212, 94, 15)), + FOREST_HILLS(18, "Wooded Hills", ColorWrapper.fromRGB(37, 86, 30)), + TAIGA_HILLS(19, "Taiga Hills", ColorWrapper.fromRGB(25, 54, 49)), + EXTREME_HILLS_EDGE(20, "Mountain Edge", ColorWrapper.fromRGB(115, 118, 157)), + JUNGLE(21, "Jungle", ColorWrapper.fromRGB(82, 122, 7)), + JUNGLE_HILLS(22, "Jungle Hills", ColorWrapper.fromRGB(46, 64, 3)), + JUNGLE_EDGE(23, "Jungle Edge", ColorWrapper.fromRGB(99, 142, 24)), + DEEP_OCEAN(24, "Deep Ocean", ColorWrapper.fromRGB(2, 0, 47)), + STONE_BEACH(25, "Stone Shore", ColorWrapper.fromRGB(162, 164, 132)), + COLD_BEACH(26, "Snowy Beach", ColorWrapper.fromRGB(250, 238, 193)), + BIRCH_FOREST(27, "Birch Forest", ColorWrapper.fromRGB(48, 117, 70)), + BIRCH_FOREST_HILLS(28, "Birch Forest Hills", ColorWrapper.fromRGB(29, 94, 51)), + ROOFED_FOREST(29, "Dark Forest", ColorWrapper.fromRGB(66, 82, 24)), + COLD_TAIGA(30, "Snowy Taiga", ColorWrapper.fromRGB(49, 85, 75)), + COLD_TAIGA_HILLS(31, "Snowy Taiga Hills", ColorWrapper.fromRGB(34, 61, 52)), + MEGA_TAIGA(32, "Giant Tree Taiga", ColorWrapper.fromRGB(92, 105, 84)), + MEGA_TAIGA_HILLS(33, "Giant Tree Taiga Hills", ColorWrapper.fromRGB(70, 76, 59)), + EXTREME_HILLS_PLUS_TREE(34, "Wooded Mountains", ColorWrapper.fromRGB(79, 111, 81)), + SAVANNA(35, "Savanna", ColorWrapper.fromRGB(192, 180, 94)), + SAVANNA_PLATEAU(36, "Savanna Plateau", ColorWrapper.fromRGB(168, 157, 98)), + MESA(37, "Badlands", ColorWrapper.fromRGB(220, 66, 19)), + MESA_PLATEAU(38, "Badlands Plateau", ColorWrapper.fromRGB(174, 152, 100)), + MESA_PLATEAU_STONE(39, "Wooded Badlands Plateau", ColorWrapper.fromRGB(202, 139, 98)), + + //fix the colors for these + WARM_OCEAN(40, "Warm Ocean", ColorWrapper.fromRGB(202, 139, 98)), + LUKEWARM_OCEAN(41, "Lukewarm Ocean", ColorWrapper.fromRGB(202, 139, 98)), + COLD_OCEAN(42, "Cold Ocean", ColorWrapper.fromRGB(202, 139, 98)), + DEEP_WARM_OCEAN(43, "Deep Warm Ocean", ColorWrapper.fromRGB(202, 139, 98)), + DEEP_LUKEWARM_OCEAN(44, "Deep Lukewarm Ocean", ColorWrapper.fromRGB(202, 139, 98)), + DEEP_COLD_OCEAN(45, "Deep Cold Ocean", ColorWrapper.fromRGB(202, 139, 98)), + DEEP_FROZEN_OCEAN(46, "Deep Frozen Ocean", ColorWrapper.fromRGB(202, 139, 98)), + LEGACY_FROZEN_OCEAN(47, "Legacy Frozen Ocean", ColorWrapper.fromRGB(202, 139, 98)), + + // Not sure are available ( need tester ) +// OCEAN_M(128, "Ocean M", ColorWrapper.fromRGB(81, 79, 195)), + + SUNFLOWER_PLAINS(129, "Sunflower Plains", ColorWrapper.fromRGB(220, 255, 177)), + DESERT_MUTATED(130, "Desert Lakes", ColorWrapper.fromRGB(255, 230, 101)), + EXTREME_HILLS_MUTATED(131, "Gravelly Mountains", ColorWrapper.fromRGB(177, 176, 174)), + FLOWER_FOREST(132, "Flower Forest", ColorWrapper.fromRGB(82, 180, 110)), + TAIGA_MUTATED(133, "Taiga Mountains", ColorWrapper.fromRGB(90, 182, 171)), + SWAMPLAND_MUTATED(134, "Swamp Hills", ColorWrapper.fromRGB(87, 255, 255)), + + // Not sure available ( need tester ) +// RIVER_M(135, "River M", ColorWrapper.fromRGB(82, 79, 255)), +// HELL_M(136, "Hell M", ColorWrapper.fromRGB(255, 80, 83)), +// SKY_M(137, "Sky M", ColorWrapper.fromRGB(210, 211, 255)), +// FROZEN_OCEAN_M(138, "Frozen Ocean M", ColorWrapper.fromRGB(226, 224, 241)), +// FROZEN_RIVER_M(139, "Frozen River M", ColorWrapper.fromRGB(239, 242, 255)), + + ICE_PLAINS_SPIKES(140, "Ice Spikes", ColorWrapper.fromRGB(223, 255, 255)), + + // Not sure available ( need tester ) +// ICE_MOUNTAINS_M(141, "Ice Mountains M", ColorWrapper.fromRGB(237, 237, 238)), +// MUSHROOM_ISLAND_M(142, "Mushroom Island M", ColorWrapper.fromRGB(255, 82, 255)), +// MUSHROOM_ISLAND_SHORE_M(143, "Mushroom Island Shore M", ColorWrapper.fromRGB(243, 82, 255)), +// BEACH_M(144, "Beach M", ColorWrapper.fromRGB(255, 255, 162)), +// DESERT_HILLS_M(145, "Desert Hills M", ColorWrapper.fromRGB(255, 177, 100)), +// FOREST_HILLS_M(146, "Forest Hills M", ColorWrapper.fromRGB(113, 167, 109)), +// TAIGA_HILLS_M(147, "Taiga Hills M", ColorWrapper.fromRGB(103, 135, 134)), +// EXTREME_HILLS_EDGE_M(148, "Extreme Hills Edge M", ColorWrapper.fromRGB(196, 203, 234)), + + JUNGLE_MUTATED(149, "Modified Jungle", ColorWrapper.fromRGB(160, 203, 92)), +// JUNGLE_HILLS_M(150, "Jungle Hills M", ColorWrapper.fromRGB(127, 146, 86)), + JUNGLE_EDGE_MUTATED(151, "Modified Jungle Edge", ColorWrapper.fromRGB(179, 217, 105)), +// DEEP_OCEAN_M(152, "Deep Ocean M", ColorWrapper.fromRGB(82, 79, 130)), +// STONE_BEACH_M(153, "Stone Beach M", ColorWrapper.fromRGB(242, 243, 209)), +// COLD_BEACH_M(154, "Cold Beach M", ColorWrapper.fromRGB(255, 255, 255)), + BIRCH_FOREST_MUTATED(155, "Tall Birch Forest", ColorWrapper.fromRGB(131, 194, 148)), + BIRCH_FOREST_HILLS_MUTATED(156, "Tall Birch Hills", ColorWrapper.fromRGB(111, 175, 133)), + ROOFED_FOREST_MUTATED(157, "Dark Forest Hills", ColorWrapper.fromRGB(143, 158, 109)), + COLD_TAIGA_MUTATED(158, "Snowy Taiga Mountains", ColorWrapper.fromRGB(132, 163, 156)), +// COLD_TAIGA_HILLS_M(159, "Cold Taiga Hills M", ColorWrapper.fromRGB(113, 143, 136)), + REDWOOD_TAIGA_MUTATED(160, "Giant Spruce Taiga", ColorWrapper.fromRGB(168, 180, 164)), + REDWOOD_TAIGA_HILLS_MUTATED(161, "Giant Spruce Taiga Hills", ColorWrapper.fromRGB(150, 158, 140)), + EXTREME_HILLS_PLUS_TREE_MUTATED(162, "Gravelly Mountains", ColorWrapper.fromRGB(161, 194, 158)), + SAVANNA_MUTATED(163, "Shattered Savanna", ColorWrapper.fromRGB(255, 255, 173)), + SAVANNA_PLATEAU_MUTATED(164, "Shattered Savanna Plateau", ColorWrapper.fromRGB(247, 238, 180)), + MESA_BRYCE(165, "Eroded Badlands", ColorWrapper.fromRGB(255, 151, 101)), + MESA_PLATEAU_MUTATED(166, "Modified Badlands Plateau", ColorWrapper.fromRGB(255, 234, 179)), + MESA_PLATEAU_STONE_MUTATED(167, "Modified Wooded Badlands Plateau", ColorWrapper.fromRGB(255, 220, 184)), + BAMBOO_JUNGLE(168, "Bamboo Jungle", ColorWrapper.fromRGB(255, 220, 184)), + BAMBOO_JUNGLE_HILLS(169, "Bamboo Jungle Hills", ColorWrapper.fromRGB(255, 220, 184)), + + // 1.16 BIOME + SOUL_SAND_VALLEY(178, "Soul Sand Valley", ColorWrapper.fromRGB(66, 113, 114)), + CRIMSON_FOREST(179, "Crimson Forest", ColorWrapper.fromRGB(141, 30, 40)), + WARPED_FOREST(180, "Warped Forest", ColorWrapper.fromRGB(22, 126, 134)), + BASALT_DELTAS(181, "Basalt Deltas", ColorWrapper.fromRGB(75, 69, 71)), + + // 1.17 BIOME ? + JAGGED_PEAKS(182, "Jagged Peaks", ColorWrapper.fromRGB(0, 0, 0)), + FROZEN_PEAKS(183, "Frozen Peaks", ColorWrapper.fromRGB(0, 0, 0)), + SNOWY_SLOPES(184, "Snowy Slopes", ColorWrapper.fromRGB(0, 0, 0)), + GROVE(185, "Grove", ColorWrapper.fromRGB(0, 0, 0)), + MEADOW(186, "Meadow", ColorWrapper.fromRGB(0, 0, 0)), + LUSH_CAVES(187, "Lush Caves", ColorWrapper.fromRGB(0, 0, 0)), + DRIPSTONE_CAVES(188, "Dripstone Caves", ColorWrapper.fromRGB(0, 0, 0)), + STONY_PEAKS(189, "Stony Peaks", ColorWrapper.fromRGB(0, 0, 0)) + ; + + private static final SparseArray biomeMap; + + static { + biomeMap = new SparseArray<>(); + for (Biome b : Biome.values()) { + biomeMap.put(b.id, b); + } + } + + public final int id; + public final String name; + public final ColorWrapper color; + + Biome(int id, String name, ColorWrapper color) { + this.id = id; + this.name = name; + this.color = color; + } + + public static Biome getBiome(int id) { + return biomeMap.get(id); + } + + + public String getName() { + return name; + } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/Block.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/Block.java deleted file mode 100644 index 1f17fd3d..00000000 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/Block.java +++ /dev/null @@ -1,904 +0,0 @@ -package com.mithrilmania.blocktopograph.map; - -import android.content.res.AssetManager; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.support.annotation.NonNull; -import android.util.SparseArray; - -import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; -import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; -import com.mithrilmania.blocktopograph.util.Color; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * Created by mithrilmania - * - * ========================== - * POCKET EDITION BLOCKS ONLY - * ========================== - * - * uvs are up to date with MCPE 0.14.0 - * - --- Please attribute @mithrilmania for generating+updating this enum - */ -public enum Block implements NamedBitmapProviderHandle, NamedBitmapProvider { - - /* - * ============================== - * Blocks - * ============================== - */ - - B_0_0_AIR("air", null, 0, 0, null, 0x00000000, false), - B_1_0_STONE("stone", "stone", 1, 0, "blocks/stone.png", 0xff464646, false), - B_1_1_STONE_GRANITE("stone", "granite", 1, 1, "blocks/stone_granite.png", 0xff8c7167, false), - B_1_2_STONE_GRANITE_SMOOTH("stone", "granite_smooth", 1, 2, "blocks/stone_granite_smooth.png", 0xff946251, false), - B_1_3_STONE_DIORITE("stone", "diorite", 1, 3, "blocks/stone_diorite.png", 0xffc6c6c6, false), - B_1_4_STONE_DIORITE_SMOOTH("stone", "diorite_smooth", 1, 4, "blocks/stone_diorite_smooth.png", 0xffbebec1, false), - B_1_5_STONE_ANDESITE("stone", "andesite", 1, 5, "blocks/stone_andesite.png", 0xff797777, false), - B_1_6_STONE_ANDESITE_SMOOTH("stone", "andesite_smooth", 1, 6, "blocks/stone_andesite_smooth.png", 0xff828382, false), - B_2_0_GRASS("grass", null, 2, 0, "blocks/grass_side_carried.png", 0xff939393, true), - B_3_0_DIRT("dirt", null, 3, 0, "blocks/dirt.png", 0xff866043, true), - B_4_0_COBBLESTONE("cobblestone", null, 4, 0, "blocks/cobblestone.png", 0xff7a7a7a, false), - B_5_0_PLANKS_OAK("planks", "oak", 5, 0, "blocks/planks_oak.png", 0xff9c7f4e, false), - B_5_1_PLANKS_SPRUCE("planks", "spruce", 5, 1, "blocks/planks_spruce.png", 0xff674d2e, false), - B_5_2_PLANKS_BIRCH("planks", "birch", 5, 2, "blocks/planks_birch.png", 0xffc3b37b, false), - B_5_3_PLANKS_JUNGLE("planks", "jungle", 5, 3, "blocks/planks_jungle.png", 0xff9a6e4d, false), - B_5_4_PLANKS_ACACIA("planks", "acacia", 5, 4, "blocks/planks_acacia.png", 0xffaa5a2f, false), - B_5_5_PLANKS_BIG_OAK("planks", "big_oak", 5, 5, "blocks/planks_big_oak.png", 0xff3b260f, false), - B_6_0_SAPLING_OAK("sapling", "oak", 6, 0, "blocks/sapling_oak.png", 0x6b476625, false), - B_6_1_SAPLING_SPRUCE("sapling", "spruce", 6, 1, "blocks/sapling_spruce.png", 0x53333a21, false), - B_6_2_SAPLING_BIRCH("sapling", "birch", 6, 2, "blocks/sapling_birch.png", 0x6b769654, false), - B_6_3_SAPLING_JUNGLE("sapling", "jungle", 6, 3, "blocks/sapling_jungle.png", 0x55305612, false), - B_6_4_SAPLING_ACACIA("sapling", "acacia", 6, 4, "blocks/sapling_acacia.png", 0xff718919, false), - B_6_5_SAPLING_BIG_OAK("sapling", "big_oak", 6, 5, "blocks/sapling_roofed_oak.png", 0xff6f522d, false), - B_7_0_BEDROCK("bedrock", null, 7, 0, "blocks/bedrock.png", 0xff535353, false), - B_8_0_FLOWING_WATER("flowing_water", null, 8, 0, "blocks/water_flow.png", 0x802e43f4, false), - B_9_0_WATER("water", null, 9, 0, "blocks/water_still.png", 0x802e43f4, false), - B_10_0_FLOWING_LAVA("flowing_lava", null, 10, 0, "blocks/lava_flow.png", 0xf0d45a12, false), - B_11_0_LAVA("lava", null, 11, 0, "blocks/lava_still.png", 0xf0d45a12, false), - B_12_0_SAND_DEFAULT("sand", "default", 12, 0, "blocks/sand.png", 0xffdbd3a0, false), - B_12_1_SAND_RED("sand", "red", 12, 1, "blocks/red_sand.png", 0xffa7531f, false), - B_13_0_GRAVEL("gravel", null, 13, 0, "blocks/gravel.png", 0xff7e7c7a, false), - B_14_0_GOLD_ORE("gold_ore", null, 14, 0, "blocks/gold_ore.png", 0xff8f8b7c, false), - B_15_0_IRON_ORE("iron_ore", null, 15, 0, "blocks/iron_ore.png", 0xff87827e, false), - B_16_0_COAL_ORE("coal_ore", null, 16, 0, "blocks/coal_ore.png", 0xff737373, false), - B_17_0_LOG_OAK("log", "oak", 17, 0, "blocks/log_oak.png", 0xff9a7d4d, false), - B_17_1_LOG_SPRUCE("log", "spruce", 17, 1, "blocks/log_spruce.png", 0xff9a7d4d, false), - B_17_2_LOG_BIRCH("log", "birch", 17, 2, "blocks/log_birch.png", 0xff9a7d4d, false), - B_17_3_LOG_JUNGLE("log", "jungle", 17, 3, "blocks/log_jungle.png", 0xff9a7d4d, false), - B_18_0_LEAVES_OAK("leaves", "oak", 18, 0, "blocks/leaves_oak.png", 0xff878787, true), - B_18_1_LEAVES_SPRUCE("leaves", "spruce", 18, 1, "blocks/leaves_spruce.png", 0xff132613, true), - B_18_2_LEAVES_BIRCH("leaves", "birch", 18, 2, "blocks/leaves_birch.png", 0xff283816, true), - B_18_3_LEAVES_JUNGLE("leaves", "jungle", 18, 3, "blocks/leaves_jungle.png", 0xff918e86, true), - B_19_0_SPONGE_DRY("sponge", "dry", 19, 0, "blocks/sponge_dry.png", 0xffb6b639, false), - B_19_1_SPONGE_WET("sponge", "wet", 19, 1, "blocks/sponge_wet.png", 0xff9b9a33, false), - B_20_0_GLASS("glass", null, 20, 0, "blocks/glass.png", 0x46daf0f4, false), - B_21_0_LAPIS_ORE("lapis_ore", null, 21, 0, "blocks/lapis_ore.png", 0xff667086, false), - B_22_0_LAPIS_BLOCK("lapis_block", null, 22, 0, "blocks/lapis_block.png", 0xff1d47a5, false), - B_23_0_DISPENSER("dispenser", null, 23, 0, "blocks/dispenser.png", 0xff606060, false), - B_24_0_SANDSTONE_DEFAULT("sandstone", "default", 24, 0, "blocks/sandstone_default.png", 0xffdad29e, false), - B_24_1_SANDSTONE_CHISELED("sandstone", "chiseled", 24, 1, "blocks/sandstone_chiseled.png", 0xffdad1a2, false), - B_24_2_SANDSTONE_SMOOTH("sandstone", "smooth", 24, 2, "blocks/sandstone_smooth.png", 0xffdad1a2, false), - B_25_0_NOTEBLOCK("noteblock", null, 25, 0, "blocks/noteblock.png", 0xff644332, false), - B_26_0_BED("bed", null, 26, 0, "blocks/bed.png", 0xff8e1616, false), - B_27_0_GOLDEN_RAIL("golden_rail", null, 27, 0, "blocks/golden_rail.png", 0xab9a6846, false), - B_28_0_DETECTOR_RAIL("detector_rail", null, 28, 0, "blocks/detector_rail.png", 0x9b786559, false), - B_29_0_STICKY_PISTON("sticky_piston", null, 29, 0, "blocks/sticky_piston.png", 0xff8d9263, false), - B_30_0_WEB("web", null, 30, 0, "blocks/web.png", 0x68dcdcdc, false), - B_31_1_TALLGRASS_FERN("tallgrass", "fern", 31, 1, "blocks/tallgrass_fern.png", 0xff747474, true), - B_31_2_TALLGRASS_GRASS("tallgrass", "grass", 31, 2, "blocks/tallgrass_grass.png", 0x4e787878, true), - B_32_0_DEADBUSH("deadbush", null, 32, 0, "blocks/deadbush.png", 0x517b4f19, false), - B_33_0_PISTON("piston", null, 33, 0, "blocks/piston.png", 0xff998159, false), - B_34_0_PISTONARMCOLLISION("pistonArmCollision", null, 34, 0, "blocks/pistonArmCollision.png", 0xff9c7f4e, false), - B_35_0_WOOL_WHITE("wool", "white", 35, 0, "blocks/wool_colored_white.png", 0xffdddddd, false), - B_35_1_WOOL_ORANGE("wool", "orange", 35, 1, "blocks/wool_colored_orange.png", 0xffdb7d3e, false), - B_35_2_WOOL_MAGENTA("wool", "magenta", 35, 2, "blocks/wool_colored_magenta.png", 0xffb350bc, false), - B_35_3_WOOL_LIGHT_BLUE("wool", "light_blue", 35, 3, "blocks/wool_colored_light_blue.png", 0xff6a8ac9, false), - B_35_4_WOOL_YELLOW("wool", "yellow", 35, 4, "blocks/wool_colored_yellow.png", 0xffb1a627, false), - B_35_5_WOOL_LIME("wool", "lime", 35, 5, "blocks/wool_colored_lime.png", 0xff41ae38, false), - B_35_6_WOOL_PINK("wool", "pink", 35, 6, "blocks/wool_colored_pink.png", 0xffd08499, false), - B_35_7_WOOL_GRAY("wool", "gray", 35, 7, "blocks/wool_colored_gray.png", 0xff404040, false), - B_35_8_WOOL_SILVER("wool", "silver", 35, 8, "blocks/wool_colored_silver.png", 0xff9aa1a1, false), - B_35_9_WOOL_CYAN("wool", "cyan", 35, 9, "blocks/wool_colored_cyan.png", 0xff2e6e89, false), - B_35_10_WOOL_PURPLE("wool", "purple", 35, 10, "blocks/wool_colored_purple.png", 0xff7e3db5, false), - B_35_11_WOOL_BLUE("wool", "blue", 35, 11, "blocks/wool_colored_blue.png", 0xff2e388d, false), - B_35_12_WOOL_BROWN("wool", "brown", 35, 12, "blocks/wool_colored_brown.png", 0xff4f321f, false), - B_35_13_WOOL_GREEN("wool", "green", 35, 13, "blocks/wool_colored_green.png", 0xff35461b, false), - B_35_14_WOOL_RED("wool", "red", 35, 14, "blocks/wool_colored_red.png", 0xff963430, false), - B_35_15_WOOL_BLACK("wool", "black", 35, 15, "blocks/wool_colored_black.png", 0xff191616, false), - B_37_0_YELLOW_FLOWER("yellow_flower", null, 37, 0, "blocks/yellow_flower.png", 0x1e6ca200, false), - B_38_0_RED_FLOWER_POPPY("red_flower", "poppy", 38, 0, "blocks/flower_poppy.png", 0x1d8a2b0d, false), - B_38_1_RED_FLOWER_BLUE_ORCHID("red_flower", "blue_orchid", 38, 1, "blocks/flower_blue_orchid.png", 0x1d188fd3, false), - B_38_2_RED_FLOWER_ALLIUM("red_flower", "allium", 38, 2, "blocks/flower_allium.png", 0x1ddbb7f8, false), - B_38_3_RED_FLOWER_HOUSTONIA("red_flower", "houstonia", 38, 3, "blocks/flower_houstonia.png", 0x1defef99, false), - B_38_4_RED_FLOWER_TULIP_RED("red_flower", "tulip_red", 38, 4, "blocks/flower_tulip_red.png", 0x1dbd2604, false), - B_38_5_RED_FLOWER_TULIP_ORANGE("red_flower", "tulip_orange", 38, 5, "blocks/flower_tulip_orange.png", 0x1dd06713, false), - B_38_6_RED_FLOWER_TULIP_WHITE("red_flower", "tulip_white", 38, 6, "blocks/flower_tulip_white.png", 0x1df9f9f9, false), - B_38_7_RED_FLOWER_TULIP_PINK("red_flower", "tulip_pink", 38, 7, "blocks/flower_tulip_pink.png", 0x1dbeb3be, false), - B_38_8_RED_FLOWER_OXEYE_DAISY("red_flower", "oxeye_daisy", 38, 8, "blocks/flower_oxeye_daisy.png", 0x1ddadada, false), - B_39_0_BROWN_MUSHROOM("brown_mushroom", null, 39, 0, "blocks/brown_mushroom.png", 0x198a6953, false), - B_40_0_RED_MUSHROOM("red_mushroom", null, 40, 0, "blocks/red_mushroom.png", 0x21c33538, false), - B_41_0_GOLD_BLOCK("gold_block", null, 41, 0, "blocks/gold_block.png", 0xfff9ec4e, false), - B_42_0_IRON_BLOCK("iron_block", null, 42, 0, "blocks/iron_block.png", 0xffdbdbdb, false), - B_43_0_DOUBLE_STONE_SLAB_STONE("double_stone_slab", "stone", 43, 0, "blocks/double_stone_slab_stone.png", 0xff9f9f9f, false), - B_43_1_DOUBLE_STONE_SLAB_SAND("double_stone_slab", "sand", 43, 1, "blocks/double_stone_slab_sand.png", 0xffdad29e, false), - B_43_2_DOUBLE_STONE_SLAB_WOOD("double_stone_slab", "wood", 43, 2, "blocks/double_stone_slab_wood.png", 0xff9c7f4e, false), - B_43_3_DOUBLE_STONE_SLAB_COBBLE("double_stone_slab", "cobble", 43, 3, "blocks/double_stone_slab_cobble.png", 0xff7a7a7a, false), - B_43_4_DOUBLE_STONE_SLAB_BRICK("double_stone_slab", "brick", 43, 4, "blocks/double_stone_slab_brick.png", 0xff926356, false), - B_43_5_DOUBLE_STONE_SLAB_SMOOTH_STONE_BRICK("double_stone_slab", "smooth_stone_brick", 43, 5, "blocks/double_stone_slab_smooth_stone_brick.png", 0xff7d7d7d, false), - B_43_6_DOUBLE_STONE_SLAB_QUARTZ("double_stone_slab", "quartz", 43, 6, "blocks/double_stone_slab_quartz.png", 0xff2c161a, false), - B_43_7_DOUBLE_STONE_SLAB_NETHER_BRICK("double_stone_slab", "nether_brick", 43, 7, "blocks/double_stone_slab_nether_brick.png", 0xffece9e2, false), - B_43_8_DOUBLE_STONE_SLAB_RED_SANDSTONE("double_stone_slab", "red_sandstone", 43, 8, "blocks/double_stone_slab_red_sandstone.png", 0xff9f9f9f, false), - B_44_0_STONE_SLAB_STONE("stone_slab", "stone", 44, 0, "blocks/stone_slab_side.png", 0xff9f9f9f, false), - B_44_1_STONE_SLAB_SAND("stone_slab", "sand", 44, 1, "blocks/stone_slab_side.png", 0xffdad29e, false), - B_44_2_STONE_SLAB_WOOD("stone_slab", "wood", 44, 2, "blocks/stone_slab_side.png", 0xff9c7f4e, false), - B_44_3_STONE_SLAB_COBBLE("stone_slab", "cobble", 44, 3, "blocks/stone_slab_side.png", 0xff7a7a7a, false), - B_44_4_STONE_SLAB_BRICK("stone_slab", "brick", 44, 4, "blocks/stone_slab_side.png", 0xff926356, false), - B_44_5_STONE_SLAB_SMOOTH_STONE_BRICK("stone_slab", "smooth_stone_brick", 44, 5, "blocks/stone_slab_side.png", 0xff7d7d7d, false), - B_44_6_STONE_SLAB_QUARTZ("stone_slab", "quartz", 44, 6, "blocks/stone_slab_side.png", 0xff2c161a, false), - B_44_7_STONE_SLAB_NETHER_BRICK("stone_slab", "nether_brick", 44, 7, "blocks/stone_slab_side.png", 0xffece9e2, false), - B_45_0_BRICK_BLOCK("brick_block", null, 45, 0, "blocks/brick_block.png", 0xff926356, false), - B_46_0_TNT("tnt", null, 46, 0, "blocks/tnt.png", 0xff82412f, false), - B_47_0_BOOKSHELF("bookshelf", null, 47, 0, "blocks/bookshelf.png", 0xff6b5839, false), - B_48_0_MOSSY_COBBLESTONE("mossy_cobblestone", null, 48, 0, "blocks/mossy_cobblestone.png", 0xff677967, false), - B_49_0_OBSIDIAN("obsidian", null, 49, 0, "blocks/obsidian.png", 0xff14121d, false), - B_50_0_TORCH("torch", null, 50, 0, "blocks/torch.png", 0x13826a3a, false), - B_51_0_FIRE("fire", null, 51, 0, "blocks/fire.png", 0x8bd38c35, false), - B_52_0_MOB_SPAWNER("mob_spawner", null, 52, 0, "blocks/mob_spawner.png", 0x9b1a2731, false), - B_53_0_OAK_STAIRS("oak_stairs", null, 53, 0, "blocks/oak_stairs.png", 0xff9c7f4e, false), - B_54_0_CHEST("chest", null, 54, 0, "blocks/chest_front.png", 0xc86f5739, false), - B_55_0_REDSTONE_WIRE("redstone_wire", null, 55, 0, "blocks/redstone_wire.png", 0x80fa1010, false), - B_56_0_DIAMOND_ORE("diamond_ore", null, 56, 0, "blocks/diamond_ore.png", 0xff818c8f, false), - B_57_0_DIAMOND_BLOCK("diamond_block", null, 57, 0, "blocks/diamond_block.png", 0xff61dbd5, false), - B_58_0_CRAFTING_TABLE("crafting_table", null, 58, 0, "blocks/crafting_table.png", 0xff6b472a, false), - B_59_0_WHEAT("wheat", null, 59, 0, "blocks/wheat.png", 0x0500b312, false), - B_60_0_FARMLAND("farmland", null, 60, 0, "blocks/farmland.png", 0xff734b2d, false), - B_61_0_FURNACE("furnace", null, 61, 0, "blocks/furnace.png", 0xff606060, false), - B_62_0_LIT_FURNACE("lit_furnace", null, 62, 0, "blocks/lit_furnace.png", 0xff606060, false), - B_63_0_STANDING_SIGN("standing_sign", null, 63, 0, "blocks/standing_sign.png", 0x566f5739, false), - B_64_0_WOODEN_DOOR("wooden_door", null, 64, 0, "blocks/wooden_door.png", 0xcf866733, false), - B_65_0_LADDER("ladder", null, 65, 0, "blocks/ladder.png", 0x8f795f34, false), - B_66_0_RAIL("rail", null, 66, 0, "blocks/rail.png", 0x8f796c58, false), - B_67_0_STONE_STAIRS("stone_stairs", null, 67, 0, "blocks/stone_stairs.png", 0xff7a7a7a, false), - B_68_0_WALL_SIGN("wall_sign", null, 68, 0, "blocks/wall_sign.png", 0x206f5739, false), - B_69_0_LEVER("lever", null, 69, 0, "blocks/lever.png", 0x136a5940, false), - B_70_0_STONE_PRESSURE_PLATE("stone_pressure_plate", null, 70, 0, "blocks/stone_pressure_plate.png", 0xff7d7d7d, false), - B_71_0_IRON_DOOR("iron_door", null, 71, 0, "blocks/iron_door.png", 0xcfbababa, false), - B_72_0_WOODEN_PRESSURE_PLATE("wooden_pressure_plate", null, 72, 0, "blocks/wooden_pressure_plate.png", 0xff9c7f4e, false), - B_73_0_REDSTONE_ORE("redstone_ore", null, 73, 0, "blocks/redstone_ore.png", 0xff846b6b, false), - B_74_0_LIT_REDSTONE_ORE("lit_redstone_ore", null, 74, 0, "blocks/lit_redstone_ore.png", 0xff846b6b, false), - B_75_0_UNLIT_REDSTONE_TORCH("unlit_redstone_torch", null, 75, 0, "blocks/unlit_redstone_torch.png", 0x465d3e26, false), - B_76_0_REDSTONE_TORCH("redstone_torch", null, 76, 0, "blocks/redstone_torch.png", 0x46a74b29, false), - B_77_0_STONE_BUTTON("stone_button", null, 77, 0, "blocks/stone_button.png", 0x28565656, false), - B_78_0_SNOW_LAYER("snow_layer", null, 78, 0, "blocks/snow_layer.png", 0xffeffbfb, false), - B_79_0_ICE("ice", null, 79, 0, "blocks/ice.png", 0x9f7dadff, false), - B_80_0_SNOW("snow", null, 80, 0, "blocks/snow.png", 0xffeffbfb, false), - B_81_0_CACTUS("cactus", null, 81, 0, "blocks/cactus.png", 0xc30d6318, false), - B_82_0_CLAY("clay", null, 82, 0, "blocks/clay.png", 0xff9ea4b0, false), - B_83_0_REEDS("reeds", null, 83, 0, "blocks/reeds.png", 0x8c94c065, false), - - B_84_0_JUKEBOX("jukebox", null, 84, 0, "blocks/fence_birch_fence.png", 0x8f463822, false), - - B_85_0_FENCE_FENCE("fence", "fence", 85, 0, "blocks/fence_fence.png", 0x8f463822, false), - B_85_1_FENCE_SPRUCE_FENCE("fence", "spruce_fence", 85, 1, "blocks/fence_spruce_fence.png", 0x8f463822, false), - B_85_2_FENCE_BIRCH_FENCE("fence", "birch_fence", 85, 2, "blocks/fence_birch_fence.png", 0x8f463822, false), - B_85_3_FENCE_JUNGLE_FENCE("fence", "jungle_fence", 85, 3, "blocks/fence_jungle_fence.png", 0x8f463822, false), - B_85_4_FENCE_ACACIA_FENCE("fence", "acacia_fence", 85, 4, "blocks/fence_acacia_fence.png", 0x8f463822, false), - B_85_5_FENCE_DARK_OAK_FENCE("fence", "dark_oak_fence", 85, 5, "blocks/fence_dark_oak_fence.png", 0x8f463822, false), - B_86_0_PUMPKIN("pumpkin", null, 86, 0, "blocks/pumpkin.png", 0xffc07615, false), - B_87_0_NETHERRACK("netherrack", null, 87, 0, "blocks/netherrack.png", 0xff6f3634, false), - B_88_0_SOUL_SAND("soul_sand", null, 88, 0, "blocks/soul_sand.png", 0xff544033, false), - B_89_0_GLOWSTONE("glowstone", null, 89, 0, "blocks/glowstone.png", 0xff8f7645, false), - B_90_0_PORTAL("portal", null, 90, 0, "blocks/portal.png", 0xc8410491, false), - B_91_0_LIT_PUMPKIN("lit_pumpkin", null, 91, 0, "blocks/lit_pumpkin.png", 0xffc07615, false), - B_92_0_CAKE("cake", null, 92, 0, "blocks/cake.png", 0xc3e4cdce, false), - B_93_0_UNPOWERED_REPEATER("unpowered_repeater", null, 93, 0, "blocks/unpowered_repeater.png", 0xff979393, false), - B_94_0_POWERED_REPEATER("powered_repeater", null, 94, 0, "blocks/powered_repeater.png", 0xffa09393, false), - B_95_0_INVISIBLEBEDROCK("invisibleBedrock", null, 95, 0, "blocks/invisibleBedrock.png", 0x3c282828, false), - B_96_0_TRAPDOOR("trapdoor", null, 96, 0, "blocks/trapdoor.png", 0xdb7e5d2d, false), - B_97_0_MONSTER_EGG_STONE("monster_egg", "stone", 97, 0, "blocks/monster_egg_stone.png", 0xff7d7d7d, false), - B_97_1_MONSTER_EGG_COBBLE("monster_egg", "cobble", 97, 1, "blocks/monster_egg_cobble.png", 0xff7a7a7a, false), - B_97_2_MONSTER_EGG_BRICK("monster_egg", "brick", 97, 2, "blocks/monster_egg_brick.png", 0xff7a7a7a, false), - B_97_3_MONSTER_EGG_MOSSYBRICK("monster_egg", "mossybrick", 97, 3, "blocks/monster_egg_mossybrick.png", 0xff7b6651, false), - B_97_4_MONSTER_EGG_CRACKEDBRICK("monster_egg", "crackedbrick", 97, 4, "blocks/monster_egg_crackedbrick.png", 0xff7b6651, false), - B_97_5_MONSTER_EGG_CHISELEDBRICK("monster_egg", "chiseledbrick", 97, 5, "blocks/monster_egg_chiseledbrick.png", 0xff7b6651, false), - B_98_0_STONEBRICK_DEFAULT("stonebrick", "default", 98, 0, "blocks/stonebrick_default.png", 0xff7a7a7a, false), - B_98_1_STONEBRICK_MOSSY("stonebrick", "mossy", 98, 1, "blocks/stonebrick_mossy.png", 0xff72776a, false), - B_98_2_STONEBRICK_CRACKED("stonebrick", "cracked", 98, 2, "blocks/stonebrick_cracked.png", 0xff767676, false), - B_98_3_STONEBRICK_CHISELED("stonebrick", "chiseled", 98, 3, "blocks/stonebrick_chiseled.png", 0xff767676, false), - B_98_4_STONEBRICK_SMOOTH("stonebrick", "smooth", 98, 4, "blocks/stonebrick_smooth.png", 0xff767676, false), - B_99_0_BROWN_MUSHROOM_BLOCK("brown_mushroom_block", null, 99, 0, "blocks/brown_mushroom_block.png", 0xff8d6a53, false), - B_100_0_RED_MUSHROOM_BLOCK("red_mushroom_block", null, 100, 0, "blocks/red_mushroom_block.png", 0xffb62524, false), - B_101_0_IRON_BARS("iron_bars", null, 101, 0, "blocks/iron_bars.png", 0x736d6c6a, false), - B_102_0_GLASS_PANE("glass_pane", null, 102, 0, "blocks/glass_pane.png", 0x1fd3eff4, false), - B_103_0_MELON_BLOCK("melon_block", null, 103, 0, "blocks/melon_block.png", 0xff979924, false), - B_104_0_PUMPKIN_STEM("pumpkin_stem", null, 104, 0, "blocks/pumpkin_stem.png", 0x1e87b759, false), - B_105_0_MELON_STEM("melon_stem", null, 105, 0, "blocks/melon_stem.png", 0x1e87b759, false), - B_106_0_VINE("vine", null, 106, 0, "blocks/vine.png", 0x8a6f6f6f, false), - B_107_0_FENCE_GATE("fence_gate", null, 107, 0, "blocks/fence_gate.png", 0x7b463822, false), - B_108_0_BRICK_STAIRS("brick_stairs", null, 108, 0, "blocks/brick_stairs.png", 0xff926356, false), - B_109_0_STONE_BRICK_STAIRS("stone_brick_stairs", null, 109, 0, "blocks/stone_brick_stairs.png", 0xff7a7a7a, false), - B_110_0_MYCELIUM("mycelium", null, 110, 0, "blocks/mycelium.png", 0xff6f6369, false), - B_111_0_WATERLILY("waterlily", null, 111, 0, "blocks/waterlily.png", 0x93335a21, false), - B_112_0_NETHER_BRICK("nether_brick", null, 112, 0, "blocks/nether_brick.png", 0xff2c161a, false), - B_113_0_NETHER_BRICK_FENCE("nether_brick_fence", null, 113, 0, "blocks/nether_brick_fence.png", 0xff2c161a, false), - B_114_0_NETHER_BRICK_STAIRS("nether_brick_stairs", null, 114, 0, "blocks/nether_brick_stairs.png", 0xff2c161a, false), - B_115_0_NETHER_WART("nether_wart", null, 115, 0, "blocks/nether_wart.png", 0x2a6a0e1e, false), - B_116_0_ENCHANTING_TABLE("enchanting_table", null, 116, 0, "blocks/enchanting_table.png", 0xff67403b, false), - B_117_0_BREWING_STAND("brewing_stand", null, 117, 0, "blocks/brewing_stand.png", 0x767c6751, false), - B_118_0_CAULDRON("cauldron", null, 118, 0, "blocks/cauldron.png", 0xff373737, false), - B_119_0_END_PORTAL("end_portal", null, 119, 0, "blocks/endframe_top.png", 0xff101010, false), - B_120_0_END_PORTAL_FRAME("end_portal_frame", null, 120, 0, "blocks/endframe_side.png", 0xff597560, false), - B_121_0_END_STONE("end_stone", null, 121, 0, "blocks/end_stone.png", 0xffdddfa5, false), - B_122_0_DRAGON_EGG("dragon_egg", null, 122, 0, "blocks/dragon_egg.png", 0xff0c090f, false), - B_123_0_REDSTONE_LAMP("redstone_lamp", null, 123, 0, "blocks/redstone_lamp.png", 0xff462b1a, false), - B_124_0_LIT_REDSTONE_LAMP("lit_redstone_lamp", null, 124, 0, "blocks/lit_redstone_lamp.png", 0xff775937, false), - B_125_0_DROPPER("dropper", null, 125, 0, "blocks/dropper.png", 0xff9c7f4e, false), - B_126_0_ACTIVATOR_RAIL("activator_rail", null, 126, 0, "blocks/activator_rail.png", 0xff9c7f4e, false), - B_127_0_COCOA("cocoa", null, 127, 0, "blocks/cocoa.png", 0x2e8a8c40, false), - B_128_0_SANDSTONE_STAIRS("sandstone_stairs", null, 128, 0, "blocks/sandstone_stairs.png", 0xffdad29e, false), - B_129_0_EMERALD_ORE("emerald_ore", null, 129, 0, "blocks/emerald_ore.png", 0xff6d8074, false), - B_130_0_ENDER_CHEST("ender_chest", null, 130, 0, "blocks/ender_chest_front.png", 0xc82c3e40, false), - B_131_0_TRIPWIRE_HOOK("tripwire_hook", null, 131, 0, "blocks/tripwire_hook.png", 0x2d8a8171, false), - B_132_0_TRIPWIRE("tripWire", null, 132, 0, "blocks/tripWire.png", 0x2d818181, false), - B_133_0_EMERALD_BLOCK("emerald_block", null, 133, 0, "blocks/emerald_block.png", 0xff51d975, false), - B_134_0_SPRUCE_STAIRS("spruce_stairs", null, 134, 0, "blocks/spruce_stairs.png", 0xff674d2e, false), - B_135_0_BIRCH_STAIRS("birch_stairs", null, 135, 0, "blocks/birch_stairs.png", 0xffc3b37b, false), - B_136_0_JUNGLE_STAIRS("jungle_stairs", null, 136, 0, "blocks/jungle_stairs.png", 0xff9a6e4d, false), - B_138_0_BEACON("beacon", null, 138, 0, "blocks/beacon.png", 0xff74ddd7, false), - B_137_0_IMPULSE_COMMAND_BLOCK("impulse_command_block", null, 137, 0, "blocks/beacon.png", 0xff9a6e4d, false), - B_137_4_IMPULSE_COMMAND_BLOCK("impulse_command_block", null, 137, 4, "blocks/beacon.png", 0xff9a6e4d, false), - B_139_0_COBBLESTONE_WALL_NORMAL("cobblestone_wall", "normal", 139, 0, "blocks/cobblestone_wall_normal.png", 0xff7a7a7a, false), - B_139_1_COBBLESTONE_WALL_MOSSY("cobblestone_wall", "mossy", 139, 1, "blocks/cobblestone_wall_mossy.png", 0xff506a50, false), - B_140_0_FLOWER_POT("flower_pot", null, 140, 0, "blocks/flower_pot.png", 0x31764133, false), - B_141_0_CARROTS("carrots", null, 141, 0, "blocks/carrots.png", 0x0901ab10, false), - B_142_0_POTATOES("potatoes", null, 142, 0, "blocks/potatoes.png", 0x0901ab10, false), - B_143_0_WOODEN_BUTTON("wooden_button", null, 143, 0, "blocks/wooden_button.png", 0x2878613e, false), - B_144_0_SKULL("skull", null, 144, 0, "blocks/skull.png", 0x8c8c8c8c, false), - B_145_0_ANVIL_INTACT("anvil", "intact", 145, 0, "blocks/anvil_intact.png", 0x9f403c3c, false), - B_145_4_ANVIL_SLIGHTLY_DAMAGED("anvil", "slightly_damaged", 145, 4, "blocks/anvil_slightly_damaged.png", 0x9f403c3c, false), - B_145_8_ANVIL_VERY_DAMAGED("anvil", "very_damaged", 145, 8, "blocks/anvil_very_damaged.png", 0x9f403c3c, false), - B_146_0_TRAPPED_CHEST("trapped_chest", null, 146, 0, "blocks/chest_front.png", 0xfe6f5739, false), - B_147_0_LIGHT_WEIGHTED_PRESSURE_PLATE("light_weighted_pressure_plate", null, 147, 0, "blocks/light_weighted_pressure_plate.png", 0xc8f9ec4e, false), - B_148_0_HEAVY_WEIGHTED_PRESSURE_PLATE("heavy_weighted_pressure_plate", null, 148, 0, "blocks/heavy_weighted_pressure_plate.png", 0xc8dbdbdb, false), - B_149_0_UNPOWERED_COMPARATOR("unpowered_comparator", null, 149, 0, "blocks/unpowered_comparator.png", 0xff9c9695, false), - B_150_0_POWERED_COMPARATOR("powered_comparator", null, 150, 0, "blocks/powered_comparator.png", 0xffa59594, false), - B_151_0_DAYLIGHT_DETECTOR("daylight_detector", null, 151, 0, "blocks/daylight_detector.png", 0xff82745e, false), - B_152_0_REDSTONE_BLOCK("redstone_block", null, 152, 0, "blocks/redstone_block.png", 0xffab1b09, false), - B_153_0_QUARTZ_ORE("quartz_ore", null, 153, 0, "blocks/quartz_ore.png", 0xffd9d1c8, false), - B_154_0_HOPPER("hopper", null, 154, 0, "blocks/hopper.png", 0xff3e3e3e, false), - B_155_0_QUARTZ_BLOCK_DEFAULT("quartz_block", "default", 155, 0, "blocks/quartz_block_default.png", 0xffece9e2, false), - B_155_1_QUARTZ_BLOCK_CHISELED("quartz_block", "chiseled", 155, 1, "blocks/quartz_block_chiseled.png", 0xffe7e4db, false), - B_155_2_QUARTZ_BLOCK_LINES("quartz_block", "lines", 155, 2, "blocks/quartz_block_lines.png", 0xffe8e5dd, false), - B_155_3_QUARTZ_BLOCK_DEFAULT("quartz_block", "default", 155, 3, "blocks/quartz_block_default.png", 0xffe7e3db, false), - B_156_0_QUARTZ_STAIRS("quartz_stairs", null, 156, 0, "blocks/quartz_stairs.png", 0xffece9e2, false), - B_157_0_DOUBLE_WOODEN_SLAB_OAK("double_wooden_slab", "oak", 157, 0, "blocks/planks_oak.png", 0xb4907449, false), - B_157_1_DOUBLE_WOODEN_SLAB_SPRUCE("double_wooden_slab", "spruce", 157, 1, "blocks/planks_spruce.png", 0xb4907449, false), - B_157_2_DOUBLE_WOODEN_SLAB_BIRCH("double_wooden_slab", "birch", 157, 2, "blocks/planks_birch.png", 0xb4907449, false), - B_157_3_DOUBLE_WOODEN_SLAB_JUNGLE("double_wooden_slab", "jungle", 157, 3, "blocks/planks_jungle.png", 0xb4907449, false), - B_157_4_DOUBLE_WOODEN_SLAB_ACACIA("double_wooden_slab", "acacia", 157, 4, "blocks/planks_acacia.png", 0xb4907449, false), - B_157_5_DOUBLE_WOODEN_SLAB_BIG_OAK("double_wooden_slab", "big_oak", 157, 5, "blocks/planks_big_oak.png", 0xb4907449, false), - B_158_0_WOODEN_SLAB_OAK("wooden_slab", "oak", 158, 0, "blocks/wooden_slab_oak.png", 0xff907449, false), - B_158_1_WOODEN_SLAB_SPRUCE("wooden_slab", "spruce", 158, 1, "blocks/wooden_slab_spruce.png", 0xff907449, false), - B_158_2_WOODEN_SLAB_BIRCH("wooden_slab", "birch", 158, 2, "blocks/wooden_slab_birch.png", 0xff907449, false), - B_158_3_WOODEN_SLAB_JUNGLE("wooden_slab", "jungle", 158, 3, "blocks/wooden_slab_jungle.png", 0xff907449, false), - B_158_4_WOODEN_SLAB_ACACIA("wooden_slab", "acacia", 158, 4, "blocks/wooden_slab_acacia.png", 0xff907449, false), - B_158_5_WOODEN_SLAB_BIG_OAK("wooden_slab", "big_oak", 158, 5, "blocks/wooden_slab_big_oak.png", 0xff907449, false), - B_159_0_STAINED_HARDENED_CLAY_WHITE("stained_hardened_clay", "white", 159, 0, "blocks/hardened_clay_stained_white.png", 0xff836f64, false), - B_159_1_STAINED_HARDENED_CLAY_ORANGE("stained_hardened_clay", "orange", 159, 1, "blocks/hardened_clay_stained_orange.png", 0xff9d5021, false), - B_159_2_STAINED_HARDENED_CLAY_MAGENTA("stained_hardened_clay", "magenta", 159, 2, "blocks/hardened_clay_stained_magenta.png", 0xff915369, false), - B_159_3_STAINED_HARDENED_CLAY_LIGHT_BLUE("stained_hardened_clay", "light_blue", 159, 3, "blocks/hardened_clay_stained_light_blue.png", 0xff706b87, false), - B_159_4_STAINED_HARDENED_CLAY_YELLOW("stained_hardened_clay", "yellow", 159, 4, "blocks/hardened_clay_stained_yellow.png", 0xffb5801f, false), - B_159_5_STAINED_HARDENED_CLAY_LIME("stained_hardened_clay", "lime", 159, 5, "blocks/hardened_clay_stained_lime.png", 0xff617030, false), - B_159_6_STAINED_HARDENED_CLAY_PINK("stained_hardened_clay", "pink", 159, 6, "blocks/hardened_clay_stained_pink.png", 0xff9c4848, false), - B_159_7_STAINED_HARDENED_CLAY_GRAY("stained_hardened_clay", "gray", 159, 7, "blocks/hardened_clay_stained_gray.png", 0xff392721, false), - B_159_8_STAINED_HARDENED_CLAY_SILVER("stained_hardened_clay", "silver", 159, 8, "blocks/hardened_clay_stained_silver.png", 0xff81655b, false), - B_159_9_STAINED_HARDENED_CLAY_CYAN("stained_hardened_clay", "cyan", 159, 9, "blocks/hardened_clay_stained_cyan.png", 0xff565959, false), - B_159_10_STAINED_HARDENED_CLAY_PURPLE("stained_hardened_clay", "purple", 159, 10, "blocks/hardened_clay_stained_purple.png", 0xff744555, false), - B_159_11_STAINED_HARDENED_CLAY_BLUE("stained_hardened_clay", "blue", 159, 11, "blocks/hardened_clay_stained_blue.png", 0xff463857, false), - B_159_12_STAINED_HARDENED_CLAY_BROWN("stained_hardened_clay", "brown", 159, 12, "blocks/hardened_clay_stained_brown.png", 0xff492e1f, false), - B_159_13_STAINED_HARDENED_CLAY_GREEN("stained_hardened_clay", "green", 159, 13, "blocks/hardened_clay_stained_green.png", 0xff484f26, false), - B_159_14_STAINED_HARDENED_CLAY_RED("stained_hardened_clay", "red", 159, 14, "blocks/hardened_clay_stained_red.png", 0xffff382b, false), - B_159_15_STAINED_HARDENED_CLAY_BLACK("stained_hardened_clay", "black", 159, 15, "blocks/hardened_clay_stained_black.png", 0xff21120d, false), - B_160_0_STAINED_GLASS_PANE_WHITE("stained_glass_pane", "white", 160, 0, "blocks/glass.png", 0x32141414, false), - B_160_1_STAINED_GLASS_PANE_ORANGE("stained_glass_pane", "orange", 160, 1, "blocks/glass.png", 0x209d5021, false), - B_160_2_STAINED_GLASS_PANE_MAGENTA("stained_glass_pane", "magenta", 160, 2, "blocks/glass.png", 0x20915369, false), - B_160_3_STAINED_GLASS_PANE_LIGHT_BLUE("stained_glass_pane", "light_blue", 160, 3, "blocks/glass.png", 0x20706b87, false), - B_160_4_STAINED_GLASS_PANE_YELLOW("stained_glass_pane", "yellow", 160, 4, "blocks/glass.png", 0x20b5801f, false), - B_160_5_STAINED_GLASS_PANE_LIME("stained_glass_pane", "lime", 160, 5, "blocks/glass.png", 0x20617030, false), - B_160_6_STAINED_GLASS_PANE_PINK("stained_glass_pane", "pink", 160, 6, "blocks/glass.png", 0x209c4848, false), - B_160_7_STAINED_GLASS_PANE_GRAY("stained_glass_pane", "gray", 160, 7, "blocks/glass.png", 0x20392721, false), - B_160_8_STAINED_GLASS_PANE_SILVER("stained_glass_pane", "silver", 160, 8, "blocks/glass.png", 0x2081655b, false), - B_160_9_STAINED_GLASS_PANE_CYAN("stained_glass_pane", "cyan", 160, 9, "blocks/glass.png", 0x20565959, false), - B_160_10_STAINED_GLASS_PANE_PURPLE("stained_glass_pane", "purple", 160, 10, "blocks/glass.png", 0x20744555, false), - B_160_11_STAINED_GLASS_PANE_BLUE("stained_glass_pane", "blue", 160, 11, "blocks/glass.png", 0x20463857, false), - B_160_12_STAINED_GLASS_PANE_BROWN("stained_glass_pane", "brown", 160, 12, "blocks/glass.png", 0x20492e1f, false), - B_160_13_STAINED_GLASS_PANE_GREEN("stained_glass_pane", "green", 160, 13, "blocks/glass.png", 0x20484f26, false), - B_160_14_STAINED_GLASS_PANE_RED("stained_glass_pane", "red", 160, 14, "blocks/glass.png", 0x20ff382b, false), - B_160_15_STAINED_GLASS_PANE_BLACK("stained_glass_pane", "black", 160, 15, "blocks/glass.png", 0x2021120d, false), - B_161_0_LEAVES2_ACACIA("leaves2", "acacia", 161, 0, "blocks/leaves2_acacia.png", 0xff2e780c, true), - B_161_1_LEAVES2_BIG_OAK("leaves2", "big_oak", 161, 1, "blocks/leaves2_big_oak.png", 0xff878787, true), - B_162_0_LOG2_ACACIA("log2", "acacia", 162, 0, "blocks/log2_acacia.png", 0xff433f39, false), - B_162_1_LOG2_BIG_OAK("log2", "big_oak", 162, 1, "blocks/log2_big_oak.png", 0xff2d2213, false), - B_163_0_ACACIA_STAIRS("acacia_stairs", null, 163, 0, "blocks/acacia_stairs.png", 0xffa95c33, false), - B_164_0_DARK_OAK_STAIRS("dark_oak_stairs", null, 164, 0, "blocks/dark_oak_stairs.png", 0xff3f2913, false), - B_165_0_SLIME("slime", null, 165, 0, "blocks/slime.png", 0xc880b672, false), - B_167_0_IRON_TRAPDOOR("iron_trapdoor", null, 167, 0, "blocks/iron_trapdoor.png", 0xb4cccccc, false), - B_168_0_PRISMARINE_ROUGH("prismarine", "rough", 168, 0, "blocks/prismarine_rough.png", 0xff426a64, false), - B_168_1_PRISMARINE_DARK("prismarine", "dark", 168, 1, "blocks/prismarine_dark.png", 0xff577a73, false), - B_168_2_PRISMARINE_BRICKS("prismarine", "bricks", 168, 2, "blocks/prismarine_bricks.png", 0xff2f483e, false), - B_169_0_SEALANTERN("seaLantern", null, 169, 0, "blocks/seaLantern.png", 0xffe0eae4, false), - B_170_0_HAY_BLOCK("hay_block", null, 170, 0, "blocks/hay_block.png", 0xffa3870e, false), - B_171_0_CARPET_WHITE("carpet", "white", 171, 0, "blocks/carpet_white.png", 0xffdddddd, false), - B_171_1_CARPET_ORANGE("carpet", "orange", 171, 1, "blocks/carpet_orange.png", 0xffdb7d3e, false), - B_171_2_CARPET_MAGENTA("carpet", "magenta", 171, 2, "blocks/carpet_magenta.png", 0xffb350bc, false), - B_171_3_CARPET_LIGHT_BLUE("carpet", "light_blue", 171, 3, "blocks/carpet_light_blue.png", 0xff6a8ac9, false), - B_171_4_CARPET_YELLOW("carpet", "yellow", 171, 4, "blocks/carpet_yellow.png", 0xffb1a627, false), - B_171_5_CARPET_LIME("carpet", "lime", 171, 5, "blocks/carpet_lime.png", 0xff41ae38, false), - B_171_6_CARPET_PINK("carpet", "pink", 171, 6, "blocks/carpet_pink.png", 0xffd08499, false), - B_171_7_CARPET_GRAY("carpet", "gray", 171, 7, "blocks/carpet_gray.png", 0xff404040, false), - B_171_8_CARPET_SILVER("carpet", "silver", 171, 8, "blocks/carpet_silver.png", 0xff9aa1a1, false), - B_171_9_CARPET_CYAN("carpet", "cyan", 171, 9, "blocks/carpet_cyan.png", 0xff2e6e89, false), - B_171_10_CARPET_PURPLE("carpet", "purple", 171, 10, "blocks/carpet_purple.png", 0xff7e3db5, false), - B_171_11_CARPET_BLUE("carpet", "blue", 171, 11, "blocks/carpet_blue.png", 0xff2e388d, false), - B_171_12_CARPET_BROWN("carpet", "brown", 171, 12, "blocks/carpet_brown.png", 0xff4f321f, false), - B_171_13_CARPET_GREEN("carpet", "green", 171, 13, "blocks/carpet_green.png", 0xff35461b, false), - B_171_14_CARPET_RED("carpet", "red", 171, 14, "blocks/carpet_red.png", 0xff963430, false), - B_171_15_CARPET_BLACK("carpet", "black", 171, 15, "blocks/carpet_black.png", 0xff191616, false), - B_172_0_HARDENED_CLAY("hardened_clay", null, 172, 0, "blocks/hardened_clay.png", 0xff5d3828, false), - B_173_0_COAL_BLOCK("coal_block", null, 173, 0, "blocks/coal_block.png", 0xff111111, false), - B_174_0_PACKED_ICE("packed_ice", null, 174, 0, "blocks/packed_ice.png", 0xff97b3e4, false), - B_175_0_DOUBLE_PLANT_SUNFLOWER("double_plant", "sunflower", 175, 0, "blocks/double_plant_sunflower.png", 0xb4d28219, false), - B_175_1_DOUBLE_PLANT_SYRINGA("double_plant", "syringa", 175, 1, "blocks/double_plant_syringa.png", 0xb4dec0e2, false), - B_175_2_DOUBLE_PLANT_GRASS("double_plant", "grass", 175, 2, "blocks/double_plant_grass.png", 0xb4334e2c, false), - B_175_3_DOUBLE_PLANT_FERN("double_plant", "fern", 175, 3, "blocks/double_plant_fern.png", 0xb43d5d34, false), - B_175_4_DOUBLE_PLANT_ROSE("double_plant", "rose", 175, 4, "blocks/double_plant_rose.png", 0xb4d10609, false), - B_175_5_DOUBLE_PLANT_PAEONIA("double_plant", "paeonia", 175, 5, "blocks/double_plant_paeonia.png", 0xb4d6c1df, false), - - B_176_0_BANNER("banner", null, 176, 0, "blocks/double_plant_paeonia.png", 0xff9aa1a1, false), - B_176_8_BANNER("banner", null, 176, 8, "blocks/double_plant_paeonia.png", 0xff9aa1a1, false), - B_176_12_BANNER("banner", null, 176, 12, "blocks/double_plant_paeonia.png", 0xff9aa1a1, false), - - B_178_0_DAYLIGHT_DETECTOR_INVERTED("daylight_detector_inverted", null, 178, 0, "blocks/daylight_detector_inverted.png", 0xffd8c9b5, false), - B_179_0_RED_SANDSTONE_DEFAULT("red_sandstone", "default", 179, 0, "blocks/red_sandstone_default.png", 0xffaa561e, false), - B_179_1_RED_SANDSTONE_CHISELED("red_sandstone", "chiseled", 179, 1, "blocks/red_sandstone_chiseled.png", 0xffa8551e, false), - B_179_2_RED_SANDSTONE_SMOOTH("red_sandstone", "smooth", 179, 2, "blocks/red_sandstone_smooth.png", 0xffcc5e16, false), - B_180_0_RED_SANDSTONE_STAIRS("red_sandstone_stairs", null, 180, 0, "blocks/red_sandstone_stairs.png", 0xffaa561e, false), - B_181_0_DOUBLE_STONE_SLAB2_RED_SANDSTONE("double_stone_slab2", "red_sandstone", 181, 0, "blocks/double_stone_slab2_red_sandstone.png", 0xffaa561e, false), - B_181_1_DOUBLE_STONE_SLAB2_PURPUR("double_stone_slab2", "purpur", 181, 1, "blocks/double_stone_slab2_purpur.png", 0xffa072a0, false), - B_182_0_STONE_SLAB2_RED_SANDSTONE("stone_slab2", "red_sandstone", 182, 0, "blocks/stone_slab2_red_sandstone.png", 0xffaa561e, false), - B_182_1_STONE_SLAB2_PURPUR("stone_slab2", "purpur", 182, 1, "blocks/stone_slab2_purpur.png", 0xffa072a0, false), - B_183_0_SPRUCE_FENCE_GATE("spruce_fence_gate", null, 183, 0, "blocks/spruce_fence_gate.png", 0x00000000, false), - B_184_0_BIRCH_FENCE_GATE("birch_fence_gate", null, 184, 0, "blocks/birch_fence_gate.png", 0x00000000, false), - B_185_0_JUNGLE_FENCE_GATE("jungle_fence_gate", null, 185, 0, "blocks/jungle_fence_gate.png", 0x00000000, false), - B_186_0_DARK_OAK_FENCE_GATE("dark_oak_fence_gate", null, 186, 0, "blocks/dark_oak_fence_gate.png", 0x00000000, false), - B_187_0_ACACIA_FENCE_GATE("acacia_fence_gate", null, 187, 0, "blocks/acacia_fence_gate.png", 0x00000000, false), - B_193_0_SPRUCE_DOOR("spruce_door", null, 193, 0, "blocks/spruce_door.png", 0x00000000, false), - B_194_0_BIRCH_DOOR("birch_door", null, 194, 0, "blocks/birch_door.png", 0x00000000, false), - B_195_0_JUNGLE_DOOR("jungle_door", null, 195, 0, "blocks/jungle_door.png", 0x00000000, false), - B_196_0_ACACIA_DOOR("acacia_door", null, 196, 0, "blocks/acacia_door.png", 0x00000000, false), - B_197_0_DARK_OAK_DOOR("dark_oak_door", null, 197, 0, "blocks/dark_oak_door.png", 0x00000000, false), - B_198_0_GRASS_PATH("grass_path", null, 198, 0, "blocks/grass_path.png", 0x46a0a0a0, false), - B_199_0_FRAME("frame", null, 199, 0, "blocks/frame.png", 0xa04f3e4f, false), - B_200_0_CHORUS_FLOWER("chorus_flower", null, 200, 0, "blocks/chorus_flower.png", 0xa0c3b6c8, false), - B_201_0_PURPUR_BLOCK_DEFAULT("purpur_block", "default", 201, 0, "blocks/purpur_block_default.png", 0xffa577a5, false), - B_201_1_PURPUR_BLOCK_CHISELED("purpur_block", "chiseled", 201, 1, "blocks/purpur_block_chiseled.png", 0xffa570a5, false), - B_201_2_PURPUR_BLOCK_LINES("purpur_block", "lines", 201, 2, "blocks/purpur_block_lines.png", 0xffa070a5, false), - B_201_3_PURPUR_BLOCK_DEFAULT("purpur_block", "default", 201, 3, "blocks/purpur_block_default.png", 0xffa577a5, false), - B_202_0_COLORED_TORCH_DEFAULT("colored_torch_rg", "default", 202, 0, "blocks/redstone_torch_on.png", 0xffa070a5, false), - B_202_9_COLORED_TORCH_DEFAULT("colored_torch_rg", "default", 202, 9, "blocks/redstone_torch_on.png", 0xffa070a5, false), - B_202_13_COLORED_TORCH_DEFAULT("colored_torch_rg", "default", 202, 13, "blocks/redstone_torch_on.png", 0xffa070a5, false), - B_203_0_PURPUR_STAIRS("purpur_stairs", null, 203, 0, "blocks/purpur_stairs.png", 0xffa577a5, false), - B_206_0_END_BRICKS("end_bricks", null, 206, 0, "blocks/end_bricks.png", 0xffe7f2af, false), - B_208_0_END_ROD("end_rod", null, 208, 0, "blocks/end_rod.png", 0xff6e6e6e, true), - B_209_0_END_GATEWAY("end_gateway", null, 209, 0, "blocks/end_gateway.png", 0xff171c27, false), - - B_205_0_SHULKERBOX("shulker_box", null, 205, 0, "blocks/observer.png", 0xffffffff, false), - B_218_0_SHULKERBOX_WHITE("shulker_box", "white", 218, 0, "blocks/observer.png", 0xffffffff, false), - B_218_1_SHULKERBOX_ORANGE("shulker_box", "orange", 218, 1, "blocks/observer.png", 0xffffd030, false), - B_218_2_SHULKERBOX_MAGENTA("shulker_box", "magenta", 218, 2, "blocks/observer.png", 0xffef007f, false), - B_218_3_SHULKERBOX_LIGHT_BLUE("shulker_box", "light_blue", 218, 3, "blocks/observer.png", 0xff5588ff, false), - B_218_4_SHULKERBOX_YELLOW("shulker_box", "yellow", 218, 4, "blocks/observer.png", 0xffffff40, false), - B_218_5_SHULKERBOX_LIME("shulker_box", "lime", 218, 5, "blocks/observer.png", 0xff0db60e, false), - B_218_6_SHULKERBOX_PINK("shulker_box", "pink", 218, 6, "blocks/observer.png", 0xffff6076, false), - B_218_7_SHULKERBOX_GRAY("shulker_box", "gray", 218, 7, "blocks/observer.png", 0xff565656, false), - B_218_8_SHULKERBOX_SILVER("shulker_box", "silver", 218, 8, "blocks/observer.png", 0xffa6a6a6, false), - B_218_9_SHULKERBOX_CYAN("shulker_box", "cyan", 218, 9, "blocks/observer.png", 0xff0d5656, false), - B_218_10_SHULKERBOX_PURPLE("shulker_box", "purple", 218, 10, "blocks/observer.png", 0xff560d56, false), - B_218_11_SHULKERBOX_BLUE("shulker_box", "blue", 218, 11, "blocks/observer.png", 0xff0d0e56, false), - B_218_12_SHULKERBOX_BROWN("shulker_box", "brown", 218, 12, "blocks/observer.png", 0xff804530, false), - B_218_13_SHULKERBOX_GREEN("shulker_box", "green", 218, 13, "blocks/observer.png", 0xff0d560e, false), - B_218_14_SHULKERBOX_RED("shulker_box", "red", 218, 14, "blocks/observer.png", 0xffff2020, false), - B_218_15_SHULKERBOX_BLACK("shulker_box", "black", 218, 15, "blocks/observer.png", 0xff000000, false), - - - B_240_0_CHORUS_PLANT("chorus_plant", null, 240, 0, "blocks/chorus_plant.png", 0xaa3d6e86, false), - B_241_0_STAINED_GLASS_WHITE("stained_glass", "white", 241, 0, "blocks/stained_glass_white.png", 0x50836f64, false), - B_241_1_STAINED_GLASS_ORANGE("stained_glass", "orange", 241, 1, "blocks/stained_glass_orange.png", 0x509d5021, false), - B_241_2_STAINED_GLASS_MAGENTA("stained_glass", "magenta", 241, 2, "blocks/stained_glass_magenta.png", 0x50915369, false), - B_241_3_STAINED_GLASS_LIGHT_BLUE("stained_glass", "light_blue", 241, 3, "blocks/stained_glass_light_blue.png", 0x50706b87, false), - B_241_4_STAINED_GLASS_YELLOW("stained_glass", "yellow", 241, 4, "blocks/stained_glass_yellow.png", 0x50b5801f, false), - B_241_5_STAINED_GLASS_LIME("stained_glass", "lime", 241, 5, "blocks/stained_glass_lime.png", 0x50617030, false), - B_241_6_STAINED_GLASS_PINK("stained_glass", "pink", 241, 6, "blocks/stained_glass_pink.png", 0x509c4848, false), - B_241_7_STAINED_GLASS_GRAY("stained_glass", "gray", 241, 7, "blocks/stained_glass_gray.png", 0x50392721, false), - B_241_8_STAINED_GLASS_SILVER("stained_glass", "silver", 241, 8, "blocks/stained_glass_silver.png", 0x5081655b, false), - B_241_9_STAINED_GLASS_CYAN("stained_glass", "cyan", 241, 9, "blocks/stained_glass_cyan.png", 0x50565959, false), - B_241_10_STAINED_GLASS_PURPLE("stained_glass", "purple", 241, 10, "blocks/stained_glass_purple.png", 0x50744555, false), - B_241_11_STAINED_GLASS_BLUE("stained_glass", "blue", 241, 11, "blocks/stained_glass_blue.png", 0x50463857, false), - B_241_12_STAINED_GLASS_BROWN("stained_glass", "brown", 241, 12, "blocks/stained_glass_brown.png", 0x50492e1f, false), - B_241_13_STAINED_GLASS_GREEN("stained_glass", "green", 241, 13, "blocks/stained_glass_green.png", 0x50484f26, false), - B_241_14_STAINED_GLASS_RED("stained_glass", "red", 241, 14, "blocks/stained_glass_red.png", 0x50ff382b, false), - B_241_15_STAINED_GLASS_BLACK("stained_glass", "black", 241, 15, "blocks/stained_glass_black.png", 0x5021120d, false), - B_243_0_PODZOL("podzol", null, 243, 0, "blocks/podzol.png", 0xff533a1b, true), - B_244_0_BEETROOT("beetroot", null, 244, 0, "blocks/beetroot.png", 0x0901ab10, false), - B_245_0_STONECUTTER("stonecutter", null, 245, 0, "blocks/stonecutter.png", 0xff515151, false), - B_246_0_GLOWINGOBSIDIAN("glowingobsidian", null, 246, 0, "blocks/glowingobsidian.png", 0xff17060a, false), - B_247_0_NETHERREACTOR_DEFAULT("netherreactor", "default", 247, 0, "blocks/netherreactor_default.png", 0xffd2d200, false), - B_247_1_NETHERREACTOR_ACTIVE("netherreactor", "active", 247, 1, "blocks/netherreactor_active.png", 0xff3d6e86, false), - B_247_2_NETHERREACTOR_COOLED("netherreactor", "cooled", 247, 2, "blocks/netherreactor_cooled.png", 0xff3d6e86, false), - B_248_0_INFO_UPDATE("info_update", null, 248, 0, "blocks/info_update.png", 0xff2f3218, false), - B_249_0_INFO_UPDATE2("info_update2", null, 249, 0, "blocks/info_update2.png", 0xff2f3218, false), - B_250_0_MOVINGBLOCK("movingBlock", null, 250, 0, "blocks/movingBlock.png", 0, false), - B_251_0_OBSERVER("observer", null, 251, 0, "blocks/observer.png", 0xff3d6e86, false), - - - - B_236_0_CONCRETE_WHITE("concrete", "orange", 236, 0, "blocks/observer.png", 0xffffffff, false), - B_236_1_CONCRETE_ORANGE("concrete", "orange", 236, 1, "blocks/observer.png", 0xffffd030, false), - B_236_2_CONCRETE_MAGENTA("concrete", "magenta", 236, 2, "blocks/observer.png", 0xffef007f, false), - B_236_3_CONCRETE_LIGHT_BLUE("concrete", "light_blue", 236, 3, "blocks/observer.png", 0xff5588ff, false), - B_236_4_CONCRETE_YELLOW("concrete", "yellow", 236, 4, "blocks/observer.png", 0xffffff40, false), - B_236_5_CONCRETE_LIME("concrete", "lime", 236, 5, "blocks/observer.png", 0xff0db60e, false), - B_236_6_CONCRETE_PINK("concrete", "pink", 236, 6, "blocks/observer.png", 0xffff6076, false), - B_236_7_CONCRETE_GRAY("concrete", "gray", 236, 7, "blocks/observer.png", 0xff565656, false), - B_236_8_CONCRETE_SILVER("concrete", "silver", 236, 8, "blocks/observer.png", 0xffa6a6a6, false), - B_236_9_CONCRETE_CYAN("concrete", "cyan", 236, 9, "blocks/observer.png", 0xff0d5656, false), - B_236_10_CONCRETE_PURPLE("concrete", "purple", 236, 10, "blocks/observer.png", 0xff560d56, false), - B_236_11_CONCRETE_BLUE("concrete", "blue", 236, 11, "blocks/observer.png", 0xff0d0e56, false), - B_236_12_CONCRETE_BROWN("concrete", "brown", 236, 12, "blocks/observer.png", 0xff804530, false), - B_236_13_CONCRETE_GREEN("concrete", "green", 236, 13, "blocks/observer.png", 0xff0d560e, false), - B_236_14_CONCRETE_RED("concrete", "red", 236, 14, "blocks/observer.png", 0xffff2020, false), - B_236_15_CONCRETE_BLACK("concrete", "black", 236, 15, "blocks/observer.png", 0xff000000, false), - - - B_237_0_CONCRETE_POWDER_WHITE("concrete_powder", "orange", 237, 0, "blocks/observer.png", 0xffffffff, false), - B_237_1_CONCRETE_POWDER_ORANGE("concrete_powder", "orange", 237, 1, "blocks/observer.png", 0xffffd030, false), - B_237_2_CONCRETE_POWDER_MAGENTA("concrete_powder", "magenta", 237, 2, "blocks/observer.png", 0xffef007f, false), - B_237_3_CONCRETE_POWDER_LIGHT_BLUE("concrete_powder", "light_blue", 237, 3, "blocks/observer.png", 0xff5588ff, false), - B_237_4_CONCRETE_POWDER_YELLOW("concrete_powder", "yellow", 237, 4, "blocks/observer.png", 0xffffff40, false), - B_237_5_CONCRETE_POWDER_LIME("concrete_powder", "lime", 237, 5, "blocks/observer.png", 0xff0db60e, false), - B_237_6_CONCRETE_POWDER_PINK("concrete_powder", "pink", 237, 6, "blocks/observer.png", 0xffff6076, false), - B_237_7_CONCRETE_POWDER_GRAY("concrete_powder", "gray", 237, 7, "blocks/observer.png", 0xff565656, false), - B_237_8_CONCRETE_POWDER_SILVER("concrete_powder", "silver", 237, 8, "blocks/observer.png", 0xffa6a6a6, false), - B_237_9_CONCRETE_POWDER_CYAN("concrete_powder", "cyan", 237, 9, "blocks/observer.png", 0xff0d5656, false), - B_237_10_CONCRETE_POWDER_PURPLE("concrete_powder", "purple", 237, 10, "blocks/observer.png", 0xff560d56, false), - B_237_11_CONCRETE_POWDER_BLUE("concrete_powder", "blue", 237, 11, "blocks/observer.png", 0xff0d0e56, false), - B_237_12_CONCRETE_POWDER_BROWN("concrete_powder", "brown", 237, 12, "blocks/observer.png", 0xff804530, false), - B_237_13_CONCRETE_POWDER_GREEN("concrete_powder", "green", 237, 13, "blocks/observer.png", 0xff0d560e, false), - B_237_14_CONCRETE_POWDER_RED("concrete_powder", "brown", 237, 14, "blocks/observer.png", 0xffff2020, false), - B_237_15_CONCRETE_POWDER_BLACK("concrete_powder", "black", 237, 15, "blocks/observer.png", 0xff000000, false), - - - B_219_2_GLAZED_TERRACOTTA_PURPLE("glazed_terracotta", "purple", 219, 2, "blocks/observer.png", 0xff762d76, false), - B_219_3_GLAZED_TERRACOTTA_PURPLE("glazed_terracotta", "purple", 219, 3, "blocks/observer.png", 0xff762d76, false), - B_219_4_GLAZED_TERRACOTTA_PURPLE("glazed_terracotta", "purple", 219, 4, "blocks/observer.png", 0xff762d76, false), - B_219_5_GLAZED_TERRACOTTA_PURPLE("glazed_terracotta", "purple", 219, 5, "blocks/observer.png", 0xff762d76, false), - B_220_2_GLAZED_TERRACOTTA_WHITE("glazed_terracotta", "white", 220, 2, "blocks/observer.png", 0xffffffff, false), - B_220_3_GLAZED_TERRACOTTA_WHITE("glazed_terracotta", "white", 220, 3, "blocks/observer.png", 0xffffffff, false), - B_220_4_GLAZED_TERRACOTTA_WHITE("glazed_terracotta", "white", 220, 4, "blocks/observer.png", 0xffffffff, false), - B_220_5_GLAZED_TERRACOTTA_WHITE("glazed_terracotta", "white", 220, 5, "blocks/observer.png", 0xffffffff, false), - B_221_2_GLAZED_TERRACOTTA_ORANGE("glazed_terracotta", "orange", 221, 2, "blocks/observer.png", 0xffff8030, false), - B_221_3_GLAZED_TERRACOTTA_ORANGE("glazed_terracotta", "orange", 221, 3, "blocks/observer.png", 0xffff8030, false), - B_221_4_GLAZED_TERRACOTTA_ORANGE("glazed_terracotta", "orange", 221, 4, "blocks/observer.png", 0xffff8030, false), - B_221_5_GLAZED_TERRACOTTA_ORANGE("glazed_terracotta", "orange", 221, 5, "blocks/observer.png", 0xffff8030, false), - B_222_2_GLAZED_TERRACOTTA_LIGHT_MAGENTA("glazed_terracotta", "magenta", 222, 2, "blocks/observer.png", 0xffff108f, false), - B_222_3_GLAZED_TERRACOTTA_LIGHT_MAGENTA("glazed_terracotta", "magenta", 222, 3, "blocks/observer.png", 0xffff108f, false), - B_222_4_GLAZED_TERRACOTTA_LIGHT_MAGENTA("glazed_terracotta", "magenta", 222, 4, "blocks/observer.png", 0xffff108f, false), - B_222_5_GLAZED_TERRACOTTA_LIGHT_MAGENTA("glazed_terracotta", "magenta", 222, 5, "blocks/observer.png", 0xffff108f, false), - B_223_2_GLAZED_TERRACOTTA_LIGHT_BLUE("glazed_terracotta", "light_blue", 223, 2, "blocks/observer.png", 0xff75a8ff, false), - B_223_3_GLAZED_TERRACOTTA_LIGHT_BLUE("glazed_terracotta", "light_blue", 223, 3, "blocks/observer.png", 0xff75a8ff, false), - B_223_4_GLAZED_TERRACOTTA_LIGHT_BLUE("glazed_terracotta", "light_blue", 223, 4, "blocks/observer.png", 0xff75a8ff, false), - B_223_5_GLAZED_TERRACOTTA_LIGHT_BLUE("glazed_terracotta", "light_blue", 223, 5, "blocks/observer.png", 0xff75a8ff, false), - B_224_0_GLAZED_TERRACOTTA_YELLOW("glazed_terracotta", "yellow", 224, 0, "blocks/observer.png", 0xffffff60, false), - B_224_2_GLAZED_TERRACOTTA_YELLOW("glazed_terracotta", "yellow", 224, 2, "blocks/observer.png", 0xffffff60, false), - B_224_3_GLAZED_TERRACOTTA_YELLOW("glazed_terracotta", "yellow", 224, 3, "blocks/observer.png", 0xffffff60, false), - B_224_4_GLAZED_TERRACOTTA_YELLOW("glazed_terracotta", "yellow", 224, 4, "blocks/observer.png", 0xffffff60, false), - B_224_5_GLAZED_TERRACOTTA_YELLOW("glazed_terracotta", "yellow", 224, 5, "blocks/observer.png", 0xffffff60, false), - B_225_0_GLAZED_TERRACOTTA_LIME("glazed_terracotta", "lime", 225, 0, "blocks/observer.png", 0xff2dd62e, false), - B_225_2_GLAZED_TERRACOTTA_LIME("glazed_terracotta", "lime", 225, 2, "blocks/observer.png", 0xff2dd62e, false), - B_225_3_GLAZED_TERRACOTTA_LIME("glazed_terracotta", "lime", 225, 3, "blocks/observer.png", 0xff2dd62e, false), - B_225_4_GLAZED_TERRACOTTA_LIME("glazed_terracotta", "lime", 225, 4, "blocks/observer.png", 0xff2dd62e, false), - B_225_5_GLAZED_TERRACOTTA_LIME("glazed_terracotta", "lime", 225, 5, "blocks/observer.png", 0xff2dd62e, false), - B_226_0_GLAZED_TERRACOTTA_PINK("glazed_terracotta", "pink", 226, 0, "blocks/observer.png", 0xffff8096, false), - B_226_2_GLAZED_TERRACOTTA_PINK("glazed_terracotta", "pink", 226, 2, "blocks/observer.png", 0xffff8096, false), - B_226_3_GLAZED_TERRACOTTA_PINK("glazed_terracotta", "pink", 226, 3, "blocks/observer.png", 0xffff8096, false), - B_226_4_GLAZED_TERRACOTTA_PINK("glazed_terracotta", "pink", 226, 4, "blocks/observer.png", 0xffff8096, false), - B_226_5_GLAZED_TERRACOTTA_PINK("glazed_terracotta", "pink", 226, 5, "blocks/observer.png", 0xffff8096, false), - B_226_6_GLAZED_TERRACOTTA_PINK("glazed_terracotta", "pink", 226, 6, "blocks/observer.png", 0xffff8096, false), - B_226_7_GLAZED_TERRACOTTA_PINK("glazed_terracotta", "pink", 226, 7, "blocks/observer.png", 0xffff8096, false), - B_227_2_GLAZED_TERRACOTTA_GRAY("glazed_terracotta", "gray", 227, 2, "blocks/observer.png", 0xff767676, false), - B_227_3_GLAZED_TERRACOTTA_GRAY("glazed_terracotta", "gray", 227, 3, "blocks/observer.png", 0xff767676, false), - B_227_4_GLAZED_TERRACOTTA_GRAY("glazed_terracotta", "gray", 227, 4, "blocks/observer.png", 0xff767676, false), - B_227_5_GLAZED_TERRACOTTA_GRAY("glazed_terracotta", "gray", 227, 5, "blocks/observer.png", 0xff767676, false), - B_228_2_GLAZED_TERRACOTTA_LIGHT_GRAY("glazed_terracotta", "light_gray", 228, 2, "blocks/observer.png", 0xffc6c6c6, false), - B_228_3_GLAZED_TERRACOTTA_LIGHT_GRAY("glazed_terracotta", "light_gray", 228, 3, "blocks/observer.png", 0xffc6c6c6, false), - B_228_4_GLAZED_TERRACOTTA_LIGHT_GRAY("glazed_terracotta", "light_gray", 228, 4, "blocks/observer.png", 0xffc6c6c6, false), - B_228_5_GLAZED_TERRACOTTA_LIGHT_GRAY("glazed_terracotta", "light_gray", 228, 5, "blocks/observer.png", 0xffc6c6c6, false), - B_229_2_GLAZED_TERRACOTTA_CYAN("glazed_terracotta", "cyan", 229, 2, "blocks/observer.png", 0xff2d7676, false), - B_229_3_GLAZED_TERRACOTTA_CYAN("glazed_terracotta", "cyan", 229, 3, "blocks/observer.png", 0xff2d7676, false), - B_229_4_GLAZED_TERRACOTTA_CYAN("glazed_terracotta", "cyan", 229, 4, "blocks/observer.png", 0xff2d7676, false), - B_229_5_GLAZED_TERRACOTTA_CYAN("glazed_terracotta", "cyan", 229, 5, "blocks/observer.png", 0xff2d7676, false), - B_231_2_GLAZED_TERRACOTTA_BLUE("glazed_terracotta", "blue", 231, 2, "blocks/observer.png", 0xff2d2e76, false), - B_231_3_GLAZED_TERRACOTTA_BLUE("glazed_terracotta", "blue", 231, 3, "blocks/observer.png", 0xff2d2e76, false), - B_231_4_GLAZED_TERRACOTTA_BLUE("glazed_terracotta", "blue", 231, 4, "blocks/observer.png", 0xff2d2e76, false), - B_231_5_GLAZED_TERRACOTTA_BLUE("glazed_terracotta", "blue", 231, 5, "blocks/observer.png", 0xff2d2e76, false), - B_232_2_GLAZED_TERRACOTTA_BROWN("glazed_terracotta", "brown", 232, 2, "blocks/observer.png", 0xffa06550, false), - B_232_3_GLAZED_TERRACOTTA_BROWN("glazed_terracotta", "brown", 232, 3, "blocks/observer.png", 0xffa06550, false), - B_232_4_GLAZED_TERRACOTTA_BROWN("glazed_terracotta", "brown", 232, 4, "blocks/observer.png", 0xffa06550, false), - B_232_5_GLAZED_TERRACOTTA_BROWN("glazed_terracotta", "brown", 232, 5, "blocks/observer.png", 0xffa06550, false), - B_233_0_GLAZED_TERRACOTTA_GREEN("glazed_terracotta", "green", 233, 0, "blocks/observer.png", 0xff2d762e, false), - B_233_2_GLAZED_TERRACOTTA_GREEN("glazed_terracotta", "green", 233, 2, "blocks/observer.png", 0xff2d762e, false), - B_233_3_GLAZED_TERRACOTTA_GREEN("glazed_terracotta", "green", 233, 3, "blocks/observer.png", 0xff2d762e, false), - B_233_4_GLAZED_TERRACOTTA_GREEN("glazed_terracotta", "green", 233, 4, "blocks/observer.png", 0xff2d762e, false), - B_233_5_GLAZED_TERRACOTTA_GREEN("glazed_terracotta", "green", 233, 5, "blocks/observer.png", 0xff2d762e, false), - B_234_2_GLAZED_TERRACOTTA_RED("glazed_terracotta", "red", 234, 2, "blocks/observer.png", 0xffff3030, false), - B_234_3_GLAZED_TERRACOTTA_RED("glazed_terracotta", "red", 234, 3, "blocks/observer.png", 0xffff3030, false), - B_234_4_GLAZED_TERRACOTTA_RED("glazed_terracotta", "red", 234, 4, "blocks/observer.png", 0xffff3030, false), - B_234_5_GLAZED_TERRACOTTA_RED("glazed_terracotta", "red", 234, 5, "blocks/observer.png", 0xffff3030, false), - B_235_2_GLAZED_TERRACOTTA_BLACK("glazed_terracotta", "black", 235, 2, "blocks/observer.png", 0xff050505, false), - B_235_3_GLAZED_TERRACOTTA_BLACK("glazed_terracotta", "black", 235, 3, "blocks/observer.png", 0xff050505, false), - B_235_4_GLAZED_TERRACOTTA_BLACK("glazed_terracotta", "black", 235, 4, "blocks/observer.png", 0xff050505, false), - B_235_5_GLAZED_TERRACOTTA_BLACK("glazed_terracotta", "black", 235, 5, "blocks/observer.png", 0xff050505, false), - - B_213_0_MAGMA_BLOCK("magma_block", "default", 213, 0, "blocks/quartz_block_default.png", 0xffc45a12, false), - - B_214_0_NETHERWART_BLOCK("netherwart_block", "default", 214, 0, "blocks/quartz_block_default.png", 0xffbf2030, false), - - B_215_0_RED_NETHER_BRICK("red_nether_brick", "default", 215, 0, "blocks/quartz_block_default.png", 0xff7f1020, false), - - B_216_0_BONE("quartz_block", "default", 216, 0, "blocks/quartz_block_default.png", 0xffefe5d2, false), - - B_255_0_RESERVED6("reserved6", null, 255, 0, "blocks/reserved6.png", 0xff19171a, false), - B_210_0_ALLOW("allow", null, 210, 0, "blocks/allow.png", 0xff634aba, false), - B_211_0_DENY("deny", null, 211, 0, "blocks/deny.png", 0xff6ca28a, false), - B_212_0_BORDER_BLOCK("border_block", null, 212, 0, "blocks/border_block.png", 0xff76a7fc, false), - B_230_0_CHALKBOARD("chalkboard", null, 230, 0, "blocks/chalkboard.png", 0xff3d6e86, false), - B_242_0_CAMERA("camera", null, 242, 0, "blocks/camera.png", 0xff3d6e86, false), - - - - - - - /* - * ============================== - * Items - * ============================== - */ - - I_256_0_IRON_SHOVEL("iron_shovel", null, 256, 0, "items/iron_shovel.png"), - I_257_0_IRON_PICKAXE("iron_pickaxe", null, 257, 0, "items/iron_pickaxe.png"), - I_258_0_IRON_AXE("iron_axe", null, 258, 0, "items/iron_axe.png"), - I_259_0_FLINT_AND_STEEL("flint_and_steel", null, 259, 0, "items/flint_and_steel.png"), - I_260_0_APPLE("apple", null, 260, 0, "items/apple.png"), - I_261_0_BOW("bow", null, 261, 0, "items/bow.png"), - I_262_0_ARROW("arrow", null, 262, 0, "items/arrow.png"), - I_263_0_COAL_COAL("coal", "coal", 263, 0, "items/coal_coal.png"), - I_263_1_COAL_CHARCOAL("coal", "charcoal", 263, 1, "items/coal_charcoal.png"), - I_264_0_DIAMOND("diamond", null, 264, 0, "items/diamond.png"), - I_265_0_IRON_INGOT("iron_ingot", null, 265, 0, "items/iron_ingot.png"), - I_266_0_GOLD_INGOT("gold_ingot", null, 266, 0, "items/gold_ingot.png"), - I_267_0_IRON_SWORD("iron_sword", null, 267, 0, "items/iron_sword.png"), - I_268_0_WOODEN_SWORD("wooden_sword", null, 268, 0, "items/wooden_sword.png"), - I_269_0_WOODEN_SHOVEL("wooden_shovel", null, 269, 0, "items/wooden_shovel.png"), - I_270_0_WOODEN_PICKAXE("wooden_pickaxe", null, 270, 0, "items/wooden_pickaxe.png"), - I_271_0_WOODEN_AXE("wooden_axe", null, 271, 0, "items/wooden_axe.png"), - I_272_0_STONE_SWORD("stone_sword", null, 272, 0, "items/stone_sword.png"), - I_273_0_STONE_SHOVEL("stone_shovel", null, 273, 0, "items/stone_shovel.png"), - I_274_0_STONE_PICKAXE("stone_pickaxe", null, 274, 0, "items/stone_pickaxe.png"), - I_275_0_STONE_AXE("stone_axe", null, 275, 0, "items/stone_axe.png"), - I_276_0_DIAMOND_SWORD("diamond_sword", null, 276, 0, "items/diamond_sword.png"), - I_277_0_DIAMOND_SHOVEL("diamond_shovel", null, 277, 0, "items/diamond_shovel.png"), - I_278_0_DIAMOND_PICKAXE("diamond_pickaxe", null, 278, 0, "items/diamond_pickaxe.png"), - I_279_0_DIAMOND_AXE("diamond_axe", null, 279, 0, "items/diamond_axe.png"), - I_280_0_STICK("stick", null, 280, 0, "items/stick.png"), - I_281_0_BOWL("bowl", null, 281, 0, "items/bowl.png"), - I_282_0_MUSHROOM_STEW("mushroom_stew", null, 282, 0, "items/mushroom_stew.png"), - I_283_0_GOLDEN_SWORD("golden_sword", null, 283, 0, "items/golden_sword.png"), - I_284_0_GOLDEN_SHOVEL("golden_shovel", null, 284, 0, "items/golden_shovel.png"), - I_285_0_GOLDEN_PICKAXE("golden_pickaxe", null, 285, 0, "items/golden_pickaxe.png"), - I_286_0_GOLDEN_AXE("golden_axe", null, 286, 0, "items/golden_axe.png"), - I_287_0_STRING("string", null, 287, 0, "items/string.png"), - I_288_0_FEATHER("feather", null, 288, 0, "items/feather.png"), - I_289_0_GUNPOWDER("gunpowder", null, 289, 0, "items/gunpowder.png"), - I_290_0_WOODEN_HOE("wooden_hoe", null, 290, 0, "items/wooden_hoe.png"), - I_291_0_STONE_HOE("stone_hoe", null, 291, 0, "items/stone_hoe.png"), - I_292_0_IRON_HOE("iron_hoe", null, 292, 0, "items/iron_hoe.png"), - I_293_0_DIAMOND_HOE("diamond_hoe", null, 293, 0, "items/diamond_hoe.png"), - I_294_0_GOLDEN_HOE("golden_hoe", null, 294, 0, "items/golden_hoe.png"), - I_295_0_WHEAT_SEEDS("wheat_seeds", null, 295, 0, "items/wheat_seeds.png"), - I_296_0_WHEAT("wheat", null, 296, 0, "items/wheat.png"), - I_297_0_BREAD("bread", null, 297, 0, "items/bread.png"), - I_298_0_LEATHER_HELMET("leather_helmet", null, 298, 0, "items/leather_helmet.png"), - I_299_0_LEATHER_CHESTPLATE("leather_chestplate", null, 299, 0, "items/leather_chestplate.png"), - I_300_0_LEATHER_LEGGINGS("leather_leggings", null, 300, 0, "items/leather_leggings.png"), - I_301_0_LEATHER_BOOTS("leather_boots", null, 301, 0, "items/leather_boots.png"), - I_302_0_CHAINMAIL_HELMET("chainmail_helmet", null, 302, 0, "items/chainmail_helmet.png"), - I_303_0_CHAINMAIL_CHESTPLATE("chainmail_chestplate", null, 303, 0, "items/chainmail_chestplate.png"), - I_304_0_CHAINMAIL_LEGGINGS("chainmail_leggings", null, 304, 0, "items/chainmail_leggings.png"), - I_305_0_CHAINMAIL_BOOTS("chainmail_boots", null, 305, 0, "items/chainmail_boots.png"), - I_306_0_IRON_HELMET("iron_helmet", null, 306, 0, "items/iron_helmet.png"), - I_307_0_IRON_CHESTPLATE("iron_chestplate", null, 307, 0, "items/iron_chestplate.png"), - I_308_0_IRON_LEGGINGS("iron_leggings", null, 308, 0, "items/iron_leggings.png"), - I_309_0_IRON_BOOTS("iron_boots", null, 309, 0, "items/iron_boots.png"), - I_310_0_DIAMOND_HELMET("diamond_helmet", null, 310, 0, "items/diamond_helmet.png"), - I_311_0_DIAMOND_CHESTPLATE("diamond_chestplate", null, 311, 0, "items/diamond_chestplate.png"), - I_312_0_DIAMOND_LEGGINGS("diamond_leggings", null, 312, 0, "items/diamond_leggings.png"), - I_313_0_DIAMOND_BOOTS("diamond_boots", null, 313, 0, "items/diamond_boots.png"), - I_314_0_GOLDEN_HELMET("golden_helmet", null, 314, 0, "items/golden_helmet.png"), - I_315_0_GOLDEN_CHESTPLATE("golden_chestplate", null, 315, 0, "items/golden_chestplate.png"), - I_316_0_GOLDEN_LEGGINGS("golden_leggings", null, 316, 0, "items/golden_leggings.png"), - I_317_0_GOLDEN_BOOTS("golden_boots", null, 317, 0, "items/golden_boots.png"), - I_318_0_FLINT("flint", null, 318, 0, "items/flint.png"), - I_319_0_PORKCHOP("porkchop", null, 319, 0, "items/porkchop.png"), - I_320_0_COOKED_PORKCHOP("cooked_porkchop", null, 320, 0, "items/cooked_porkchop.png"), - I_321_0_PAINTING("painting", null, 321, 0, "items/painting.png"), - I_322_0_GOLDEN_APPLE("golden_apple", null, 322, 0, "items/golden_apple.png"), - I_323_0_SIGN("sign", null, 323, 0, "items/sign.png"), - I_324_0_WOODEN_DOOR("wooden_door", null, 324, 0, "items/wooden_door.png"), - I_325_0_BUCKET_BUCKET("bucket", "bucket", 325, 0, "items/bucket_bucket.png"), - I_325_1_BUCKET_MILK("bucket", "milk", 325, 1, "items/bucket_milk.png"), - I_325_8_BUCKET_BUCKET_WATER("bucket", "bucket_water", 325, 8, "items/bucket_bucket_water.png"), - I_325_10_BUCKET_BUCKET_LAVA("bucket", "bucket_lava", 325, 10, "items/bucket_bucket_lava.png"), - I_328_0_MINECART("minecart", null, 328, 0, "items/minecart.png"), - I_329_0_SADDLE("saddle", null, 329, 0, "items/saddle.png"), - I_330_0_IRON_DOOR("iron_door", null, 330, 0, "items/iron_door.png"), - I_331_0_REDSTONE("redstone", null, 331, 0, "items/redstone.png"), - I_332_0_SNOWBALL("snowball", null, 332, 0, "items/snowball.png"), - I_333_0_BOAT_OAK("boat", "oak", 333, 0, "items/boat_oak.png"), - I_333_1_BOAT_SPRUCE("boat", "spruce", 333, 1, "items/boat_spruce.png"), - I_333_2_BOAT_BIRCH("boat", "birch", 333, 2, "items/boat_birch.png"), - I_333_3_BOAT_JUNGLE("boat", "jungle", 333, 3, "items/boat_jungle.png"), - I_333_4_BOAT_ACACIA("boat", "acacia", 333, 4, "items/boat_acacia.png"), - I_333_5_BOAT_BIG_OAK("boat", "big_oak", 333, 5, "items/boat_big_oak.png"), - I_334_0_LEATHER("leather", null, 334, 0, "items/leather.png"), - I_336_0_BRICK("brick", null, 336, 0, "items/brick.png"), - I_337_0_CLAY_BALL("clay_ball", null, 337, 0, "items/clay_ball.png"), - I_338_0_REEDS("reeds", null, 338, 0, "items/reeds.png"), - I_339_0_PAPER("paper", null, 339, 0, "items/paper.png"), - I_340_0_BOOK("book", null, 340, 0, "items/book.png"), - I_341_0_SLIME_BALL("slime_ball", null, 341, 0, "items/slime_ball.png"), - I_342_0_CHEST_MINECART("chest_minecart", null, 342, 0, "items/chest_minecart.png"), - I_344_0_EGG("egg", null, 344, 0, "items/egg.png"), - I_345_0_COMPASS("compass", null, 345, 0, "items/compass.png"), - I_346_0_FISHING_ROD("fishing_rod", null, 346, 0, "items/fishing_rod.png"), - I_347_0_CLOCK("clock", null, 347, 0, "items/clock.png"), - I_348_0_GLOWSTONE_DUST("glowstone_dust", null, 348, 0, "items/glowstone_dust.png"), - I_349_0_FISH("fish", null, 349, 0, "items/fish.png"), - I_350_0_COOKED_FISH("cooked_fish", null, 350, 0, "items/cooked_fish.png"), - I_351_0_DYE_BLACKINKSAC("dye", "black", 351, 0, "items/dye_powder_black.png"), - I_351_1_DYE_RED("dye", "red", 351, 1, "items/dye_powder_red.png"), - I_351_2_DYE_GREEN("dye", "green", 351, 2, "items/dye_powder_green.png"), - I_351_3_DYE_BROWNCOCOABEANS("dye", "brown", 351, 3, "items/dye_powder_brown.png"), - I_351_4_DYE_BLUE("dye", "blue", 351, 4, "items/dye_powder_blue.png"), - I_351_5_DYE_PURPLE("dye", "purple", 351, 5, "items/dye_powder_purple.png"), - I_351_6_DYE_CYAN("dye", "cyan", 351, 6, "items/dye_powder_cyan.png"), - I_351_7_DYE_SILVER("dye", "silver", 351, 7, "items/dye_powder_silver.png"), - I_351_8_DYE_GRAY("dye", "gray", 351, 8, "items/dye_powder_gray.png"), - I_351_9_DYE_PINK("dye", "pink", 351, 9, "items/dye_powder_pink.png"), - I_351_10_DYE_LIME("dye", "lime", 351, 10, "items/dye_powder_lime.png"), - I_351_11_DYE_YELLOW("dye", "yellow", 351, 11, "items/dye_powder_yellow.png"), - I_351_12_DYE_LIGHT_BLUE("dye", "light_blue", 351, 12, "items/dye_powder_light_blue.png"), - I_351_13_DYE_MAGENTA("dye", "magenta", 351, 13, "items/dye_powder_magenta.png"), - I_351_14_DYE_ORANGE("dye", "orange", 351, 14, "items/dye_powder_orange.png"), - I_351_15_DYE_WHITEBONEMEAL("dye", "white", 351, 15, "items/dye_powder_white.png"), - I_352_0_BONE("bone", null, 352, 0, "items/bone.png"), - I_353_0_SUGAR("sugar", null, 353, 0, "items/sugar.png"), - I_354_0_CAKE("cake", null, 354, 0, "items/cake.png"), - I_355_0_BED("bed", null, 355, 0, "items/bed.png"), - I_356_0_REPEATER("repeater", null, 356, 0, "items/repeater.png"), - I_357_0_COOKIE("cookie", null, 357, 0, "items/cookie.png"), - I_358_0_MAP_FILLED("map_filled", null, 358, 0, "items/map_filled.png"), - I_359_0_SHEARS("shears", null, 359, 0, "items/shears.png"), - I_360_0_MELON("melon", null, 360, 0, "items/melon.png"), - I_361_0_PUMPKIN_SEEDS("pumpkin_seeds", null, 361, 0, "items/pumpkin_seeds.png"), - I_362_0_MELON_SEEDS("melon_seeds", null, 362, 0, "items/melon_seeds.png"), - I_363_0_BEEF("beef", null, 363, 0, "items/beef.png"), - I_364_0_COOKED_BEEF("cooked_beef", null, 364, 0, "items/cooked_beef.png"), - I_365_0_CHICKEN("chicken", null, 365, 0, "items/chicken.png"), - I_366_0_COOKED_CHICKEN("cooked_chicken", null, 366, 0, "items/cooked_chicken.png"), - I_367_0_ROTTEN_FLESH("rotten_flesh", null, 367, 0, "items/rotten_flesh.png"), - I_368_0_ENDER_PEARL("ender_pearl", null, 368, 0, "items/ender_pearl.png"), - I_369_0_BLAZE_ROD("blaze_rod", null, 369, 0, "items/blaze_rod.png"), - I_370_0_GHAST_TEAR("ghast_tear", null, 370, 0, "items/ghast_tear.png"), - I_371_0_GOLD_NUGGET("gold_nugget", null, 371, 0, "items/gold_nugget.png"), - I_372_0_NETHER_WART("nether_wart", null, 372, 0, "items/nether_wart.png"), - I_373_0_POTION("potion", null, 373, 0, "items/potion.png"), - I_374_0_GLASS_BOTTLE("glass_bottle", null, 374, 0, "items/glass_bottle.png"), - I_375_0_SPIDER_EYE("spider_eye", null, 375, 0, "items/spider_eye.png"), - I_376_0_FERMENTED_SPIDER_EYE("fermented_spider_eye", null, 376, 0, "items/fermented_spider_eye.png"), - I_377_0_BLAZE_POWDER("blaze_powder", null, 377, 0, "items/blaze_powder.png"), - I_378_0_MAGMA_CREAM("magma_cream", null, 378, 0, "items/magma_cream.png"), - I_379_0_BREWING_STAND("brewing_stand", null, 379, 0, "items/brewing_stand.png"), - I_380_0_CAULDRON("cauldron", null, 380, 0, "items/cauldron.png"), - I_381_0_ENDER_EYE("ender_eye", null, 381, 0, "items/ender_eye.png"), - I_382_0_SPECKLED_MELON("speckled_melon", null, 382, 0, "items/speckled_melon.png"), - I_383_0_SPAWN_EGG("spawn_egg", null, 383, 0, "items/spawn_egg.png"), - I_384_0_EXPERIENCE_BOTTLE("experience_bottle", null, 384, 0, "items/experience_bottle.png"), - I_385_0_FIREBALL("fireball", null, 385, 0, "items/fireball.png"), - I_388_0_EMERALD("emerald", null, 388, 0, "items/emerald.png"), - I_389_0_FRAME("frame", null, 389, 0, "items/frame.png"), - I_390_0_FLOWER_POT("flower_pot", null, 390, 0, "items/flower_pot.png"), - I_391_0_CARROT("carrot", null, 391, 0, "items/carrot.png"), - I_392_0_POTATO("potato", null, 392, 0, "items/potato.png"), - I_393_0_BAKED_POTATO("baked_potato", null, 393, 0, "items/baked_potato.png"), - I_394_0_POISONOUS_POTATO("poisonous_potato", null, 394, 0, "items/poisonous_potato.png"), - I_395_0_EMPTYMAP("emptyMap", null, 395, 0, "items/emptyMap.png"), - I_396_0_GOLDEN_CARROT("golden_carrot", null, 396, 0, "items/golden_carrot.png"), - I_397_0_SKULL_SKELETON("skull", "skeleton", 397, 0, "items/skull_skeleton.png"), - I_397_1_SKULL_WITHER("skull", "wither", 397, 1, "items/skull_wither.png"), - I_397_2_SKULL_ZOMBIE("skull", "zombie", 397, 2, "items/skull_zombie.png"), - I_397_3_SKULL_PLAYER("skull", "player", 397, 3, "items/skull_player.png"), - I_397_4_SKULL_CREEPER("skull", "creeper", 397, 4, "items/skull_creeper.png"), - I_397_5_SKULL_DRAGON("skull", "dragon", 397, 5, "items/skull_dragon.png"), - I_398_0_CARROTONASTICK("carrotOnAStick", null, 398, 0, "items/carrotOnAStick.png"), - I_399_0_NETHERSTAR("netherStar", null, 399, 0, "items/netherStar.png"), - I_400_0_PUMPKIN_PIE("pumpkin_pie", null, 400, 0, "items/pumpkin_pie.png"), - I_403_0_ENCHANTED_BOOK("enchanted_book", null, 403, 0, "items/enchanted_book.png"), - I_404_0_COMPARATOR("comparator", null, 404, 0, "items/comparator.png"), - I_405_0_NETHERBRICK("netherbrick", null, 405, 0, "items/netherbrick.png"), - I_406_0_QUARTZ("quartz", null, 406, 0, "items/quartz.png"), - I_407_0_TNT_MINECART("tnt_minecart", null, 407, 0, "items/tnt_minecart.png"), - I_408_0_HOPPER_MINECART("hopper_minecart", null, 408, 0, "items/hopper_minecart.png"), - I_409_0_PRISMARINE_SHARD("prismarine_shard", null, 409, 0, "items/prismarine_shard.png"), - I_410_0_HOPPER("hopper", null, 410, 0, "items/hopper.png"), - I_411_0_RABBIT("rabbit", null, 411, 0, "items/rabbit.png"), - I_412_0_COOKED_RABBIT("cooked_rabbit", null, 412, 0, "items/cooked_rabbit.png"), - I_413_0_RABBIT_STEW("rabbit_stew", null, 413, 0, "items/rabbit_stew.png"), - I_414_0_RABBIT_FOOT("rabbit_foot", null, 414, 0, "items/rabbit_foot.png"), - I_415_0_RABBIT_HIDE("rabbit_hide", null, 415, 0, "items/rabbit_hide.png"), - I_416_0_HORSEARMORLEATHER("horsearmorleather", null, 416, 0, "items/horsearmorleather.png"), - I_417_0_HORSEARMORIRON("horsearmoriron", null, 417, 0, "items/horsearmoriron.png"), - I_418_0_HORSEARMORGOLD("horsearmorgold", null, 418, 0, "items/horsearmorgold.png"), - I_419_0_HORSEARMORDIAMOND("horsearmordiamond", null, 419, 0, "items/horsearmordiamond.png"), - I_420_0_LEAD("lead", null, 420, 0, "items/lead.png"), - I_421_0_NAMETAG("nameTag", null, 421, 0, "items/nameTag.png"), - I_422_0_PRISMARINE_CRYSTALS("prismarine_crystals", null, 422, 0, "items/prismarine_crystals.png"), - I_423_0_MUTTONRAW("muttonRaw", null, 423, 0, "items/muttonRaw.png"), - I_424_0_MUTTONCOOKED("muttonCooked", null, 424, 0, "items/muttonCooked.png"), - I_426_0_END_CRYSTAL("end_crystal", null, 426, 0, "items/end_crystal.png"), - I_427_0_SPRUCE_DOOR("spruce_door", null, 427, 0, "items/spruce_door.png"), - I_428_0_BIRCH_DOOR("birch_door", null, 428, 0, "items/birch_door.png"), - I_429_0_JUNGLE_DOOR("jungle_door", null, 429, 0, "items/jungle_door.png"), - I_430_0_ACACIA_DOOR("acacia_door", null, 430, 0, "items/acacia_door.png"), - I_431_0_DARK_OAK_DOOR("dark_oak_door", null, 431, 0, "items/dark_oak_door.png"), - I_432_0_CHORUS_FRUIT("chorus_fruit", null, 432, 0, "items/chorus_fruit.png"), - I_433_0_CHORUS_FRUIT_POPPED("chorus_fruit_popped", null, 433, 0, "items/chorus_fruit_popped.png"), - I_437_0_DRAGON_BREATH("dragon_breath", null, 437, 0, "items/dragon_breath.png"), - I_438_0_SPLASH_POTION("splash_potion", null, 438, 0, "items/splash_potion.png"), - I_441_0_LINGERING_POTION("lingering_potion", null, 441, 0, "items/lingering_potion.png"), - I_444_0_ELYTRA("elytra", null, 444, 0, "items/elytra.png"), - I_457_0_BEETROOT("beetroot", null, 457, 0, "items/beetroot.png"), - I_458_0_BEETROOT_SEEDS("beetroot_seeds", null, 458, 0, "items/seeds_beetroot.png"), - I_459_0_BEETROOT_SOUP("beetroot_soup", null, 459, 0, "items/beetroot_soup.png"), - I_460_0_SALMON("salmon", null, 460, 0, "items/fish_salmon.png"), - I_461_0_CLOWNFISH("clownfish", null, 461, 0, "items/fish_clownfish.png"), - I_462_0_PUFFERFISH("pufferfish", null, 462, 0, "items/fish_pufferfish.png"), - I_463_0_COOKED_SALMON("cooked_salmon", null, 463, 0, "items/fish_salmon_cooked.png"), - I_466_0_APPLEENCHANTED("apple_enchanted", null, 466, 0, "items/apple_golden.png"), - I_454_0_BOARD_ONE_BY_ONE("board", "one_by_one", 454, 0, "items/chalkboard_small.png"), - I_454_1_BOARD_TWO_BY_ONE("board", "two_by_one", 454, 1, "items/chalkboard_medium.png"), - I_454_2_BOARD_THREE_BY_TWO("board", "three_by_two", 454, 2, "items/chalkboard_large.png"), - I_456_0_PORTFOLIO("portfolio", null, 456, 0, "items/portfolio.png"), - I_498_0_CAMERA("camera", null, 498, 0, "items/camera.png"); - - - public final int id, subId; - - public final String name, subName, displayName, identifier; - - public final String texPath; - - public final Color color; - public final boolean hasBiomeShading; - - - public Bitmap bitmap; - - Block(String name, String subName, int id, int subId, String texPath, int color, boolean hasBiomeShading){ - this.id = id; - this.subId = subId; - this.name = name; - this.subName = subName; - this.displayName = name + " " + subName; - this.texPath = texPath; - this.color = Color.fromARGB(color); - this.hasBiomeShading = hasBiomeShading; - this.identifier = "minecraft:" + subName; - } - - Block(String name, String subName, int id, int subId, String texPath){ - this.id = id; - this.subId = subId; - this.name = name; - this.subName = subName; - this.displayName = name + " " + subName; - this.texPath = texPath; - this.color = null; - this.hasBiomeShading = false; - this.identifier = "minecraft:" + subName; - } - - @Override - public Bitmap getBitmap(){ - return this.bitmap; - } - - @NonNull - @Override - public NamedBitmapProvider getNamedBitmapProvider(){ - return this; - } - - @NonNull - @Override - public String getBitmapDisplayName(){ - return this.displayName; - } - - @NonNull - @Override - public String getBitmapDataName(){ - return name + "@" + subName; - } - - private static final Map byDataName = new HashMap<>(); - private static final SparseArray> blockMap; - static { - blockMap = new SparseArray<>(); - SparseArray subMap; - for(Block b : Block.values()){ - subMap = blockMap.get(b.id); - if(subMap == null){ - subMap = new SparseArray<>(); - blockMap.put(b.id, subMap); - } - subMap.put(b.subId, b); - if(b.subId == 0) byDataName.put(b.name, b); - byDataName.put(b.name + "@" + b.subName, b); - } - } - - public static Block getByDataName(String dataName){ - return byDataName.get(dataName); - } - - public static void loadBitmaps(AssetManager assetManager) throws IOException { - for(Block b : Block.values()){ - if(b.bitmap == null && b.texPath != null){ - try { - b.bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(assetManager.open(b.texPath)), 32, 32, false); - } catch(FileNotFoundException e){ - //TODO file-paths were generated from block names; some do not actually exist... - //Log.w("File not found! "+b.texPath); - } catch (Exception e){ - e.printStackTrace(); - } - } - } - } - - public static Block getBlock(int id, int meta){ - if(id < 0) return null; - SparseArray subMap = blockMap.get(id); - if(subMap == null) return null; - else return subMap.get(meta); - } - -} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/CustomIcon.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/CustomIcon.java index 3a57176b..e2476334 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/CustomIcon.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/CustomIcon.java @@ -3,7 +3,7 @@ import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/Dimension.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/Dimension.java index 2d5e2c13..c99e4562 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/Dimension.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/Dimension.java @@ -1,6 +1,9 @@ package com.mithrilmania.blocktopograph.map; +import androidx.annotation.StringRes; + +import com.mithrilmania.blocktopograph.R; import com.mithrilmania.blocktopograph.map.renderer.MapType; import java.util.HashMap; @@ -9,7 +12,7 @@ public enum Dimension { OVERWORLD(0, "overworld", "Overworld", 16, 16, 128, 1, MapType.OVERWORLD_SATELLITE), - NETHER(1, "nether", "Nether", 16, 16, 128, 8, MapType.NETHER), + NETHER(1, "nether", "Nether", 16, 16, 128, 1, MapType.NETHER), END(2, "end", "End", 16, 16, 128, 1, MapType.END_SATELLITE);//mcpe: SOON^TM /jk public final int id; @@ -18,7 +21,7 @@ public enum Dimension { public final String dataName, name; public final MapType defaultMapType; - Dimension(int id, String dataName, String name, int chunkW, int chunkL, int chunkH, int dimensionScale, MapType defaultMapType){ + Dimension(int id, String dataName, String name, int chunkW, int chunkL, int chunkH, int dimensionScale, MapType defaultMapType) { this.id = id; this.dataName = dataName; this.name = name; @@ -29,22 +32,37 @@ public enum Dimension { this.defaultMapType = defaultMapType; } + @StringRes + + public int getName() { + switch (this) { + case OVERWORLD: + return R.string.overworld; + case NETHER: + return R.string.nether; + case END: + return R.string.the_end; + default: + return 0; + } + } + private static Map dimensionMap = new HashMap<>(); static { - for(Dimension dimension : Dimension.values()){ + for (Dimension dimension : Dimension.values()) { dimensionMap.put(dimension.dataName, dimension); } } - public static Dimension getDimension(String dataName){ - if(dataName == null) return null; + public static Dimension getDimension(String dataName) { + if (dataName == null) return null; return dimensionMap.get(dataName.toLowerCase()); } - public static Dimension getDimension(int id){ - for(Dimension dimension : values()){ - if(dimension.id == id) return dimension; + public static Dimension getDimension(int id) { + for (Dimension dimension : values()) { + if (dimension.id == id) return dimension; } return null; } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/Entity.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/Entity.java index 2f250962..60db008d 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/Entity.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/Entity.java @@ -3,123 +3,151 @@ import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.support.annotation.NonNull; + +import androidx.annotation.NonNull; import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; /* -Entity enum for MCPE -- by @mithrilmania +Entity enum for MCPE __ by @mithrilmania + +___ Please attribute @mithrilmania for generating+updating this enum + + Format: + + ENTITY( + numeric_id, deprecated! + Display Name, + DataName, not used? + wiki_name, as identifier, originally dumped as wiki-name cases. + icon + ) + + icon is from assets/entity_wiki.png which was download from + https://d1u5p3l4wpay3k.cloudfront.net/minecraft_gamepedia/4/40/EntityCSS.png ---- Please attribute @mithrilmania for generating+updating this enum */ public enum Entity implements NamedBitmapProviderHandle, NamedBitmapProvider { - - CHICKEN(10, "Chicken", new String[]{ "Chicken" }, "chicken", 4), - COW(11, "Cow", new String[]{ "Cow" }, "cow", 3), - PIG(12, "Pig", new String[]{ "Pig" }, "pig", 1), - SHEEP(13, "Sheep", new String[]{ "Sheep" }, "sheep", 2), - WOLF(14, "Wolf", new String[]{ "Wolf" }, "wolf", 18), - VILLAGER(15, "Villager", new String[]{ "Villager" }, "villager", 7), - MUSHROOM_COW(16, "Mooshroom", new String[]{ "MushroomCow" }, "mooshroom", 6), - SQUID(17, "Squid", new String[]{ "Squid" }, "squid", 5), - RABBIT(18, "Rabbit", new String[]{ "Rabbit" }, "rabbit", 89), - BAT(19, "Bat", new String[]{ "Bat" }, "bat", 64), - VILLAGER_GOLEM(20, "Iron Golem", new String[]{ "VillagerGolem", "IronGolem" }, "iron-golem", 48), - SNOW_MAN(21, "Snow Golem", new String[]{ "SnowMan", "SnowGolem" }, "snow-golem", 31), - OZELOT(22, "Ocelot", new String[]{ "Ozelot", "Ocelot" }, "ozelot", 37), - HORSE(23, "Donkey", new String[]{ "EntityHorse", "Horse" }, "horse", 73), - HORSE_DONKEY(24, "Donkey", new String[]{ "EntityHorse", "Donkey" }, "donkey", 74), - HORSE_MULE(25, "Mule", new String[]{ "EntityHorse", "Mule" }, "mule", 75), - HORSE_SKELETON(26, "Skeleten Horse", new String[]{ "EntityHorse", "SkeletonHorse" }, "skeleton-horse", 76), - HORSE_ZOMBIE(27, "Zombie Horse", new String[]{ "EntityHorse", "ZombieHorse" }, "zombie-horse", 77), + CHICKEN(10, "Chicken", new String[]{"Chicken", "chicken"}, "chicken", 4), + COW(11, "Cow", new String[]{"Cow", "cow"}, "cow", 3), + PIG(12, "Pig", new String[]{"Pig", "pig"}, "pig", 1), + SHEEP(13, "Sheep", new String[]{"Sheep", "sheep"}, "sheep", 2), + WOLF(14, "Wolf", new String[]{"Wolf", "wolf"}, "wolf", 18), + VILLAGER(15, "Villager", new String[]{"Villager", "villager", "villager_v2"}, "villager", 7), + MUSHROOM_COW(16, "Mooshroom", new String[]{"MushroomCow", "mushroomcow", "mooshroom"}, "mooshroom", 6), + SQUID(17, "Squid", new String[]{"Squid", "squid"}, "squid", 5), + RABBIT(18, "Rabbit", new String[]{"Rabbit", "rabbit"}, "rabbit", 89), + BAT(19, "Bat", new String[]{"Bat", "bat"}, "bat", 64), + VILLAGER_GOLEM(20, "Iron Golem", new String[]{"VillagerGolem", "IronGolem", "villagergolem", "irongolem", "iron-golem", "iron_golem"}, "iron-golem", 48), + SNOW_MAN(21, "Snow Golem", new String[]{"SnowMan", "SnowGolem", "snowman", "snowgolem", "snow-golem"}, "snow-golem", 31), + OZELOT(22, "Ocelot", new String[]{"Ozelot", "Ocelot", "ozelot", "ocelot", "cat"}, "ozelot", 37), + HORSE(23, "Horse", new String[]{"EntityHorse", "Horse", "entityhorse", "horse"}, "horse", 73), + HORSE_DONKEY(24, "Donkey", new String[]{"EntityHorse", "Donkey", "donkey"}, "donkey", 74), + HORSE_MULE(25, "Mule", new String[]{"EntityHorse", "Mule", "mule"}, "mule", 75), + HORSE_SKELETON(26, "Skeleten Horse", new String[]{"skeleton_horse", "EntityHorse", "SkeletonHorse", "skeletonhorse", "skeleton-horse"}, "skeleton-horse", 76), + HORSE_ZOMBIE(27, "Zombie Horse", new String[]{"EntityHorse", "ZombieHorse", "zombiehorse", "zombie-horse"}, "zombie-horse", 77), //28 //29 - ARMOR_STAND(30, "Armor Stand", new String[]{ "ArmorStand" }, "TODO", 106),//30 ; ArmorStand is not yet in the game + ARMOR_STAND(30, "Armor Stand", new String[]{"ArmorStand", "armorstand"}, "TODO", 106), //31 - ZOMBIE(32, "Zombie", new String[]{ "Zombie" }, "zombie", 9), - CREEPER(33, "Creeper", new String[]{ "Creeper" }, "creeper", 14), - SKELETON(34, "Skeleton", new String[]{ "Skeleton" }, "skeleton", 10), - SPIDER(35, "Spider", new String[]{ "Spider" }, "spider", 11), - PIG_ZOMBIE(36, "Zombie Pigman", new String[]{ "PigZombie" }, "zombie-pigman", 17), - SLIME(37, "Slime", new String[]{ "Slime" }, "slime", 15), - ENDERMAN(38, "Enderman", new String[]{ "Enderman", "EnderMan" }, "enderman", 21), - SILVERFISH(39, "Silverfish", new String[]{ "Silverfish" }, "silverfish", 22), - CAVE_SPIDER(40, "Cave Spider", new String[]{ "CaveSpider" }, "cave-spider", 13), - GHAST(41, "Ghast", new String[]{ "Ghast" }, "ghast", 16), - LAVA_SLIME(42, "Magma Cube", new String[]{ "LavaSlime" }, "magma-cube", 24), - BLAZE(43, "Blaze", new String[]{ "Blaze" }, "blaze", 32), - ZOMBIE_VILLAGER(44, "Zombie Villager", new String[]{ "ZombieVillager" }, "zombie-villager", 62), - WITCH(45, "Witch", new String[]{ "Witch" }, "witch", 54), - SKELETON_STRAY(46, "Stray", new String[]{ "Skeleton", "StraySkeleton" }, "stray", 98), - ZOMBIE_HUSK(47, "Husk", new String[]{ "Zombie", "HuskZombie" }, "husk", 99), - SKELETON_WITHER(48, "Wither Skeleton", new String[]{ "Skeleton", "WitherSkeleton" }, "wither", 61), - GUARDIAN(49, "Guardian", new String[]{ "Guardian" }, "guardian", 87), - ELDER_GAURDIAN(50, "Elder Gaurdian", new String[]{ "ElderGaurdian" }, "elder-gaurdian", 88), - NPC(51, "NPC", new String[]{ "Npc" }, "npc", 100), - WITHER_BOSS(52, "Wither Boss", new String[]{ "WitherBoss" }, "blue-wither-skull", 72), - ENDER_DRAGON(53, "Ender Dragon", new String[]{ "EnderDragon" }, "ender-dragon", 29), - SHULKER(54, "Shulker", new String[]{ "Shulker" }, "shulker", 30), - ENDERMITE(55, "Endermite", new String[]{ "Endermite" }, "endermite", 86), - LEARN_TO_CODE_MASCOT(56, "Learn To Code Mascot", new String[]{ "LearnToCodeMascot" }, "learn-to-code-mascot", 108), - GIANT(57, "Giant Zombie", new String[]{ "Giant" }, "giant", 9),//53 ; Giant is not yet in the game + ZOMBIE(32, "Zombie", new String[]{"Zombie", "zombie"}, "zombie", 9), + CREEPER(33, "Creeper", new String[]{"Creeper", "creeper"}, "creeper", 14), + SKELETON(34, "Skeleton", new String[]{"Skeleton", "skeleton"}, "skeleton", 10), + SPIDER(35, "Spider", new String[]{"Spider", "spider"}, "spider", 12), + PIG_ZOMBIE(36, "Zombie Pigman", new String[]{"PigZombie", "pigzombie", "zombie-pigman", "zombie_pigman"}, "zombie-pigman", 17), + SLIME(37, "Slime", new String[]{"Slime", "slime"}, "slime", 15), + ENDERMAN(38, "Enderman", new String[]{"Enderman", "EnderMan", "enderman"}, "enderman", 21), + SILVERFISH(39, "Silverfish", new String[]{"Silverfish", "silverfish"}, "silverfish", 22), + CAVE_SPIDER(40, "Cave Spider", new String[]{"CaveSpider", "cavespider", "cave-spider", "cave_spider"}, "cave-spider", 118), + GHAST(41, "Ghast", new String[]{"Ghast", "ghast"}, "ghast", 16), + LAVA_SLIME(42, "Magma Cube", new String[]{"LavaSlime", "lavaslime", "magma-cube", "magma_cube"}, "magma-cube", 24), + BLAZE(43, "Blaze", new String[]{"Blaze", "blaze"}, "blaze", 32), + ZOMBIE_VILLAGER(44, "Zombie Villager", new String[]{"ZombieVillager", "zombievillager", "zombie_villager_v2", "zombie_villager"}, "zombie-villager", 62), + WITCH(45, "Witch", new String[]{"Witch", "witch"}, "witch", 54), + SKELETON_STRAY(46, "Stray", new String[]{"Skeleton", "StraySkeleton", "strayskeleton", "stray"}, "stray", 98), + ZOMBIE_HUSK(47, "Husk", new String[]{"Zombie", "HuskZombie", "husk", "huskzombie"}, "husk", 99), + SKELETON_WITHER(48, "Wither Skeleton", new String[]{"Skeleton", "WitherSkeleton", "wither", "wither_skeleton"}, "wither", 61), + GUARDIAN(49, "Guardian", new String[]{"Guardian", "guardian"}, "guardian", 87), + ELDER_GAURDIAN(50, "Elder Gaurdian", new String[]{"ElderGaurdian", "elder-guardian", "elderguardian"}, "elder-gaurdian", 88), + NPC(51, "NPC", new String[]{"Npc", "npc"}, "npc", 100), + WITHER_BOSS(52, "Wither Boss", new String[]{"WitherBoss", "witherboss", "blue-wither-skull"}, "blue-wither-skull", 72), + ENDER_DRAGON(53, "Ender Dragon", new String[]{"EnderDragon", "ender-dragon", "enderdragon"}, "ender-dragon", 29), + SHULKER(54, "Shulker", new String[]{"Shulker", "shukler", "shulker"}, "shulker", 30), + ENDERMITE(55, "Endermite", new String[]{"Endermite", "endermite"}, "endermite", 86), + LEARN_TO_CODE_MASCOT(56, "Learn To Code Mascot", new String[]{"LearnToCodeMascot", "learntocodemascot", "learn-to-code-mascot"}, "learn-to-code-mascot", 108), + GIANT(57, "Giant Zombie", new String[]{"Giant", "giant"}, "giant", 9),//53 ; Giant is not yet in the game //58 //59 //60 //61 //61 - CAMERA(62, "Tripod Camera", new String[]{ "TripodCamera" }, "camera", 144), - PLAYER(63, "Player", new String[]{ "Player" }, "player", 8), - ITEM(64, "Dropped Item", new String[]{ "ItemEntity" }, "item", -1),//do not render items - PRIMED_TNT(65, "Primed TNT", new String[]{ "PrimedTnt" }, "primed-tnt", 49), - FALLING_SAND(66, "Falling Block", new String[]{ "FallingBlock" }, "falling-sand", 50), - ITEM_FRAME(67, "Item Frame", new String[]{ "ItemFrame" }, "empty-item-frame", 66),//67 ; ItemFrame is not yet in the game - THROWN_EXP_BOTTLE(68, "Bottle o' Enchanting", new String[]{ "ThrownExpBottle", "ExperiencePotion" }, "ThrownExpBottle", 56), - XP_ORB(69, "Experience Orb", new String[]{ "XPOrb", "ExperienceOrb" }, "experience-orb", 59), - EYE_OF_ENDER_SIGNAL(70, "Eye of Ender", new String[]{ "EyeOfEnderSignal" }, "eye-of-ender", 47), - ENDER_CRYSTAL(71, "Ender Crystal", new String[]{ "EnderCrystal" }, "ender-crystal", 52), + CAMERA(62, "Tripod Camera", new String[]{"TripodCamera", "camera"}, "camera", 144), + PLAYER(63, "Player", new String[]{"Player", "player"}, "player", 8), + ITEM(64, "Dropped Item", new String[]{"ItemEntity", "item"}, "item", -1),//do not render items + PRIMED_TNT(65, "Primed TNT", new String[]{"PrimedTnt", "primedtnt", "primed-tnt"}, "primed-tnt", 49), + FALLING_SAND(66, "Falling Block", new String[]{"FallingBlock", "falling-sand", "fallingblock"}, "falling-sand", 50), + ITEM_FRAME(67, "Item Frame", new String[]{"ItemFrame", "itemframe", "empty-item-frame"}, "empty-item-frame", 66),//67 ; ItemFrame is not yet in the game + THROWN_EXP_BOTTLE(68, "Bottle o' Enchanting", new String[]{"ThrownExpBottle", "ExperiencePotion", "thrownexpbottle"}, "ThrownExpBottle", 56), + XP_ORB(69, "Experience Orb", new String[]{"XPOrb", "ExperienceOrb", "experience-orb", "experienceorb", "xp_orb"}, "experience-orb", 59), + EYE_OF_ENDER_SIGNAL(70, "Eye of Ender", new String[]{"EyeOfEnderSignal", "eyeofendersignal", "eye-of-ender"}, "eye-of-ender", 47), + ENDER_CRYSTAL(71, "Ender Crystal", new String[]{"EnderCrystal", "endercrystal", "ender-crystal"}, "ender-crystal", 52), //72 //73 - TURTLE(74, "Turtle", new String[]{ "Turtle" }, "turtle", 79), + //74 //75 - SHULKER_BULLET(76, "Shulker Bullet", new String[]{ "ShulkerBullet" }, "shulker-bullet", 79), - FISHING_HOOK(77, "Fishing Hook", new String[]{ "FishingHook" }, "fishing-hook", 57), - CHALKBOARD(78, "Chalkboard", new String[]{ "Chalkboard" }, "chalkboard", 144), - DRAGON_FIREBALL(79, "Dragon Fireball", new String[]{ "DragonFireball" }, "dragon-fireball", 80), - ARROW(80, "Arrow", new String[]{ "Arrow" }, "arrow", 41), - SNOWBALL(81, "Snowball", new String[]{ "Snowball" }, "snowball", 42), - THROWN_EGG(82, "Thrown Egg", new String[]{ "ThrownEgg" }, "thrown-egg", 43), - PAINTING(83, "Painting", new String[]{ "Painting" }, "painting", 65), - MINECART_RIDEABLE(84, "Minecart", new String[]{ "MinecartRideable", "Minecart" }, "minecart", 34), - LARGE_FIREBALL(85, "Ghast Fireball", new String[]{ "Fireball", "LargeFireball" }, "fireball", 44), - THROWN_POTION(86, "Splash Potion", new String[]{ "ThrownPotion" }, "ThrownPotion", 95), - THROWN_ENDERPEARL(87, "Ender Pearl", new String[]{ "ThrownEnderpearl" }, "ender-pearl", 46), - LEASH_KNOT(88, "Lead Knot", new String[]{ "LeashKnot", "LeashFenceKnotEntity" }, "lead-knot", 94), - WITHER_SKULL(89, "Wither Skull", new String[]{ "WitherSkull" }, "wither-skull", 60), - BOAT(90, "Boat", new String[]{ "Boat" }, "boat", 33), + SHULKER_BULLET(76, "Shulker Bullet", new String[]{"ShulkerBullet", "shulkerbullet", "shulker-bullet"}, "shulker-bullet", 79), + FISHING_HOOK(77, "Fishing Hook", new String[]{"FishingHook", "fishinghook", "fishing-hook"}, "fishing-hook", 57), + CHALKBOARD(78, "Chalkboard", new String[]{"Chalkboard", "chalkboard"}, "chalkboard", 144), + DRAGON_FIREBALL(79, "Dragon Fireball", new String[]{"DragonFireball", "dragonfireball", "dragon-fireball"}, "dragon-fireball", 80), + ARROW(80, "Arrow", new String[]{"Arrow", "arrow"}, "arrow", 41), + SNOWBALL(81, "Snowball", new String[]{"Snowball", "snowball"}, "snowball", 42), + THROWN_EGG(82, "Thrown Egg", new String[]{"ThrownEgg", "thrownegg", "thrown-egg"}, "thrown-egg", 43), + PAINTING(83, "Painting", new String[]{"Painting", "painting"}, "painting", 65), + MINECART_RIDEABLE(84, "Minecart", new String[]{"MinecartRideable", "Minecart", "minecart"}, "minecart", 34), + LARGE_FIREBALL(85, "Ghast Fireball", new String[]{"Fireball", "LargeFireball", "fireball", "largefireball"}, "fireball", 44), + THROWN_POTION(86, "Splash Potion", new String[]{"ThrownPotion", "thrownpotion"}, "ThrownPotion", 95), + THROWN_ENDERPEARL(87, "Ender Pearl", new String[]{"ThrownEnderpearl", "thrownenderpearl", "ender-pearl"}, "ender-pearl", 46), + LEASH_KNOT(88, "Lead Knot", new String[]{"LeashKnot", "LeashFenceKnotEntity", "lead-knot", "leashknot", "leashfenceknotentity", "leash_knot"}, "lead-knot", 94), + WITHER_SKULL(89, "Wither Skull", new String[]{"WitherSkull", "wither-skull", "witherskull"}, "wither-skull", 60), + BOAT(90, "Boat", new String[]{"Boat", "boat"}, "boat", 33), //91 //92 - LIGHTNING(93, "Lightning Bolt", new String[]{ "LightningBolt" }, "lightning", 58), - SMALL_FIREBALL(94, "Blaze Fireball", new String[]{ "SmallFireball" }, "fireball", 44), - AREA_EFFECT_CLOUD(95, "Area effect cloud", new String[]{ "AreaEffectCloud" }, "area-effect-cloud", 144), - MINECART_HOPPER(96, "Minecart with Hopper", new String[]{ "MinecartHopper" }, "minecart-with-hopper", 70), - MINECART_TNT(97, "Minecart with TNT", new String[]{ "MinecartTNT" }, "minecart-with-tnt", 69), - MINECART_CHEST(98, "Storage Minecart", new String[]{ "MinecartChest" }, "minecart-chest", 35), - LINGERING_POTION(101, "Lingering potion", new String[]{ "LingeringPotion" }, "lingering-potion", 144), - - CAT(122, "Cat", new String[]{ "Cat" }, "cat", 144),//95 ; FireworksRocketEntity is not in the game yet - PANDA(123, "Panda", new String[]{ "Panda" }, "panda", 144),//95 ; FireworksRocketEntity is not in the game yet + LIGHTNING(93, "Lightning Bolt", new String[]{"LightningBolt", "lightning", "lightningbolt"}, "lightning", 58), + SMALL_FIREBALL(94, "Blaze Fireball", new String[]{"SmallFireball", "smallfireball"}, "fireball", 44), + AREA_EFFECT_CLOUD(95, "Area effect cloud", new String[]{"AreaEffectCloud", "area-effect-cloud", "areaeffectcloud"}, "area-effect-cloud", 144), + MINECART_HOPPER(96, "Minecart with Hopper", new String[]{"MinecartHopper", "minecart-with-hopper", "minecarthopper"}, "minecart-with-hopper", 70), + MINECART_TNT(97, "Minecart with TNT", new String[]{"MinecartTNT", "minecart-with-tnt", "minecarttnt"}, "minecart-with-tnt", 69), + MINECART_CHEST(98, "Storage Minecart", new String[]{"MinecartChest", "minecart-chest", "minecartchest", "chest_minecart", "chestminecart"}, "minecart-chest", 35), + LINGERING_POTION(101, "Lingering potion", new String[]{"LingeringPotion", "lingeringpotion", "lingering-potion"}, "lingering-potion", 144), //id 900+ is ignored for functions like map-filtering, these are placeholders for when the game adds more expected features. - MINECART_SPAWNER(900, "Minecart with Spawner", new String[]{ "MinecartSpawner" }, "minecart-with-spawner", 71),//99 ; MinecartSpawner is not yet in the game - MINECART_COMMAND_BLOCK(901, "Minecart with Command Block", new String[]{ "MinecartCommandBlock" }, "minecart-with-command-block", 78),//100 ; MinecartCommandBlock is not yet in the game - MINECART_FURNACE(902, "Powered Minecart", new String[]{ "MinecartFurnace" }, "minecart-furnace", 36),//101 ; MinecartFurnace is not yet in the game - FIREWORKS_ROCKET_ENTITY(903, "Firework Rocket", new String[]{ "FireworksRocketEntity" }, "fireworks-rocket", 144),//95 ; FireworksRocketEntity is not in the game yet - UNKNOWN(999, "Unknown", new String[]{ "Unknown" }, "unknown", 144); + MINECART_SPAWNER(900, "Minecart with Spawner", new String[]{"MinecartSpawner", "minecart-with-spawner", "minecartspawner"}, "minecart-with-spawner", 71),//99 ; MinecartSpawner is not yet in the game + MINECART_COMMAND_BLOCK(901, "Minecart with Command Block", new String[]{"MinecartCommandBlock", "minecartcommandblock", "minecart-with-command-block"}, "minecart-with-command-block", 78),//100 ; MinecartCommandBlock is not yet in the game + MINECART_FURNACE(902, "Powered Minecart", new String[]{"MinecartFurnace", "minecartfurnace", "minecart-furnace"}, "minecart-furnace", 36), + FIREWORKS_ROCKET_ENTITY(903, "Firework Rocket", new String[]{"FireworksRocketEntity", "fireworksrocketentity", "fireworks-rocket"}, "fireworks-rocket", 144),//95 ; FireworksRocketEntity is not in the game yet + PILLAGER(102, "Pillager", new String[]{"pillager"}, "pillager", 102), + DROWNED(103, "Drowned", new String[]{"drowned"}, "drowned", 133), + PUFFERFISH(104, "Pufferfish", new String[]{"pufferfish"}, "pufferfish", 129), + + LLAMA(105, "Llama", new String[]{"llama"}, "llama", 101), + TROPICALFISH(106, "TropicalFish", new String[]{"tropicalfish"}, "tropicalfish", 130), + PARROT(107, "Parrot", new String[]{"parrot"}, "parrot", 109), + COD(108, "Cod", new String[]{"cod"}, "cod", 126), + SALMON(109, "Salmon", new String[]{"salmon"}, "salmon", 128), + TURTLE(110, "Turtle", new String[]{"turtle"}, "turtle", 123), + DOLPHIN(111, "Dolphin", new String[]{"dolphin"}, "dolphin", 135), + WANDERINGTRADER(112, "WanderingTrader", new String[]{"wandering_trader"}, "wanderingtrader", 281), + PHANTOM(113, "Phantom", new String[]{"phantom"}, "phantom", 125), + + THROWNTRIDENT(114, "ThrownTrident", new String[]{"thrown_trident"}, "throwntrident", 124), + UNKNOWN(999, "Unknown", new String[]{"Unknown", "unknown"}, "unknown", 144), + + CAT(122, "Cat", new String[]{"Cat"}, "cat", 142),//95 ; FireworksRocketEntity is not in the game yet + PANDA(123, "Panda", new String[]{"Panda"}, "panda", 136);//95 ; FireworksRocketEntity is not in the game yet + public final int id, sheetPos; public final String displayName, wikiName; @@ -128,7 +156,7 @@ public enum Entity implements NamedBitmapProviderHandle, NamedBitmapProvider { public Bitmap bitmap; - Entity(int id, String displayName, String[] dataNames, String wikiName, int sheetPos){ + Entity(int id, String displayName, String[] dataNames, String wikiName, int sheetPos) { this.id = id; this.displayName = displayName; this.dataNames = dataNames; @@ -137,20 +165,25 @@ public enum Entity implements NamedBitmapProviderHandle, NamedBitmapProvider { this.identifier = "minecraft:" + wikiName; } + @NonNull @Override - public Bitmap getBitmap(){ - return this.bitmap; + public Bitmap getBitmap() { + if (bitmap != null) return bitmap; + if (Entity.UNKNOWN.bitmap == null) { + Entity.UNKNOWN.bitmap = Bitmap.createBitmap(24, 24, Bitmap.Config.RGB_565); + } + return Entity.UNKNOWN.bitmap; } @NonNull @Override - public NamedBitmapProvider getNamedBitmapProvider(){ + public NamedBitmapProvider getNamedBitmapProvider() { return this; } @NonNull @Override - public String getBitmapDisplayName(){ + public String getBitmapDisplayName() { return this.displayName; } @@ -162,52 +195,40 @@ public String getBitmapDataName() { return this.dataNames[0]; } - private static final Map entityMap; - private static final Map entityByID; - - static { - entityMap = new HashMap<>(); - entityByID = new HashMap<>(); - for(Entity e : Entity.values()){ - for(String dataName : e.dataNames){ - entityMap.put(dataName, e); - } - entityByID.put(e.id, e); + public static Entity getEntity(@NonNull String identifier) { + int i = identifier.indexOf(':'); + if (i != -1) { + if (!"minecraft".equals(identifier.substring(0, i))) return Entity.UNKNOWN; + identifier = identifier.substring(i + 1); } - } - - public static Entity getEntity(String dataName){ - try { - return entityMap.get(dataName); + for (Entity e : Entity.values()) { + if (identifier.equals(e.wikiName)) return e; } - catch (Exception e) - { - android.util.Log.d("myTag","error finding id for: " + dataName); - return entityMap.get(dataName); + identifier = identifier.replace("_", ""); + for (Entity e : Entity.values()) { + for (String dataName : e.dataNames) + if (dataName.toLowerCase().equals(identifier)) + return e; } + return Entity.UNKNOWN; } - public static Entity getEntity(int id){ - try { - return entityByID.get(id); - } - catch (Exception e ) - { - android.util.Log.d("myTag","error finding id for: " + id); - return entityByID.get(id); + public static Entity getEntity(int id) { + for (Entity e : Entity.values()) { + if (id == e.id) return e; } + return Entity.UNKNOWN; } - public static void loadEntityBitmaps(AssetManager assetManager) throws IOException { Bitmap sheet = BitmapFactory.decodeStream(assetManager.open("entity_wiki.png")); int w = sheet.getWidth(); int tileSize = 16; - for(Entity e : Entity.values()){ - if(e.bitmap == null && e.sheetPos >= 0){ + for (Entity e : Entity.values()) { + if (e.bitmap == null && e.sheetPos >= 0) { //sheetpos; first sprite has pos 1. - int p = (e.sheetPos-1) * tileSize; + int p = (e.sheetPos - 1) * tileSize; int x = p % w; int y = ((p - x) / w) * tileSize; //read tile from sheet, scale to 32x32 diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/FloatPaneFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/FloatPaneFragment.java new file mode 100644 index 00000000..5fdfe797 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/FloatPaneFragment.java @@ -0,0 +1,16 @@ +package com.mithrilmania.blocktopograph.map; + +import androidx.fragment.app.Fragment; + +public abstract class FloatPaneFragment extends Fragment { + + protected FloatPaneFragment.OnCloseButtonClickListener mOnCloseButtonClickListener; + + public void setOnCloseButtonClickListener(OnCloseButtonClickListener onCloseButtonClickListener) { + mOnCloseButtonClickListener = onCloseButtonClickListener; + } + + public interface OnCloseButtonClickListener { + void onCloseButtonClick(); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/Item.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/Item.java new file mode 100644 index 00000000..fe8b963f --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/Item.java @@ -0,0 +1,343 @@ +package com.mithrilmania.blocktopograph.map; + +import android.content.res.AssetManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.SparseArray; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.util.ColorWrapper; +import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; +import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public enum Item implements NamedBitmapProviderHandle, NamedBitmapProvider { + + /* + * ============================== + * Blocks + * ============================== + */ + + I_256_0_IRON_SHOVEL("iron_shovel", null, 256, 0, "items/iron_shovel.png"), + I_257_0_IRON_PICKAXE("iron_pickaxe", null, 257, 0, "items/iron_pickaxe.png"), + I_258_0_IRON_AXE("iron_axe", null, 258, 0, "items/iron_axe.png"), + I_259_0_FLINT_AND_STEEL("flint_and_steel", null, 259, 0, "items/flint_and_steel.png"), + I_260_0_APPLE("apple", null, 260, 0, "items/apple.png"), + I_261_0_BOW("bow", null, 261, 0, "items/bow.png"), + I_262_0_ARROW("arrow", null, 262, 0, "items/arrow.png"), + I_263_0_COAL_COAL("coal", "coal", 263, 0, "items/coal_coal.png"), + I_263_1_COAL_CHARCOAL("coal", "charcoal", 263, 1, "items/coal_charcoal.png"), + I_264_0_DIAMOND("diamond", null, 264, 0, "items/diamond.png"), + I_265_0_IRON_INGOT("iron_ingot", null, 265, 0, "items/iron_ingot.png"), + I_266_0_GOLD_INGOT("gold_ingot", null, 266, 0, "items/gold_ingot.png"), + I_267_0_IRON_SWORD("iron_sword", null, 267, 0, "items/iron_sword.png"), + I_268_0_WOODEN_SWORD("wooden_sword", null, 268, 0, "items/wooden_sword.png"), + I_269_0_WOODEN_SHOVEL("wooden_shovel", null, 269, 0, "items/wooden_shovel.png"), + I_270_0_WOODEN_PICKAXE("wooden_pickaxe", null, 270, 0, "items/wooden_pickaxe.png"), + I_271_0_WOODEN_AXE("wooden_axe", null, 271, 0, "items/wooden_axe.png"), + I_272_0_STONE_SWORD("stone_sword", null, 272, 0, "items/stone_sword.png"), + I_273_0_STONE_SHOVEL("stone_shovel", null, 273, 0, "items/stone_shovel.png"), + I_274_0_STONE_PICKAXE("stone_pickaxe", null, 274, 0, "items/stone_pickaxe.png"), + I_275_0_STONE_AXE("stone_axe", null, 275, 0, "items/stone_axe.png"), + I_276_0_DIAMOND_SWORD("diamond_sword", null, 276, 0, "items/diamond_sword.png"), + I_277_0_DIAMOND_SHOVEL("diamond_shovel", null, 277, 0, "items/diamond_shovel.png"), + I_278_0_DIAMOND_PICKAXE("diamond_pickaxe", null, 278, 0, "items/diamond_pickaxe.png"), + I_279_0_DIAMOND_AXE("diamond_axe", null, 279, 0, "items/diamond_axe.png"), + I_280_0_STICK("stick", null, 280, 0, "items/stick.png"), + I_281_0_BOWL("bowl", null, 281, 0, "items/bowl.png"), + I_282_0_MUSHROOM_STEW("mushroom_stew", null, 282, 0, "items/mushroom_stew.png"), + I_283_0_GOLDEN_SWORD("golden_sword", null, 283, 0, "items/golden_sword.png"), + I_284_0_GOLDEN_SHOVEL("golden_shovel", null, 284, 0, "items/golden_shovel.png"), + I_285_0_GOLDEN_PICKAXE("golden_pickaxe", null, 285, 0, "items/golden_pickaxe.png"), + I_286_0_GOLDEN_AXE("golden_axe", null, 286, 0, "items/golden_axe.png"), + I_287_0_STRING("string", null, 287, 0, "items/string.png"), + I_288_0_FEATHER("feather", null, 288, 0, "items/feather.png"), + I_289_0_GUNPOWDER("gunpowder", null, 289, 0, "items/gunpowder.png"), + I_290_0_WOODEN_HOE("wooden_hoe", null, 290, 0, "items/wooden_hoe.png"), + I_291_0_STONE_HOE("stone_hoe", null, 291, 0, "items/stone_hoe.png"), + I_292_0_IRON_HOE("iron_hoe", null, 292, 0, "items/iron_hoe.png"), + I_293_0_DIAMOND_HOE("diamond_hoe", null, 293, 0, "items/diamond_hoe.png"), + I_294_0_GOLDEN_HOE("golden_hoe", null, 294, 0, "items/golden_hoe.png"), + I_295_0_WHEAT_SEEDS("wheat_seeds", null, 295, 0, "items/wheat_seeds.png"), + I_296_0_WHEAT("wheat", null, 296, 0, "items/wheat.png"), + I_297_0_BREAD("bread", null, 297, 0, "items/bread.png"), + I_298_0_LEATHER_HELMET("leather_helmet", null, 298, 0, "items/leather_helmet.png"), + I_299_0_LEATHER_CHESTPLATE("leather_chestplate", null, 299, 0, "items/leather_chestplate.png"), + I_300_0_LEATHER_LEGGINGS("leather_leggings", null, 300, 0, "items/leather_leggings.png"), + I_301_0_LEATHER_BOOTS("leather_boots", null, 301, 0, "items/leather_boots.png"), + I_302_0_CHAINMAIL_HELMET("chainmail_helmet", null, 302, 0, "items/chainmail_helmet.png"), + I_303_0_CHAINMAIL_CHESTPLATE("chainmail_chestplate", null, 303, 0, "items/chainmail_chestplate.png"), + I_304_0_CHAINMAIL_LEGGINGS("chainmail_leggings", null, 304, 0, "items/chainmail_leggings.png"), + I_305_0_CHAINMAIL_BOOTS("chainmail_boots", null, 305, 0, "items/chainmail_boots.png"), + I_306_0_IRON_HELMET("iron_helmet", null, 306, 0, "items/iron_helmet.png"), + I_307_0_IRON_CHESTPLATE("iron_chestplate", null, 307, 0, "items/iron_chestplate.png"), + I_308_0_IRON_LEGGINGS("iron_leggings", null, 308, 0, "items/iron_leggings.png"), + I_309_0_IRON_BOOTS("iron_boots", null, 309, 0, "items/iron_boots.png"), + I_310_0_DIAMOND_HELMET("diamond_helmet", null, 310, 0, "items/diamond_helmet.png"), + I_311_0_DIAMOND_CHESTPLATE("diamond_chestplate", null, 311, 0, "items/diamond_chestplate.png"), + I_312_0_DIAMOND_LEGGINGS("diamond_leggings", null, 312, 0, "items/diamond_leggings.png"), + I_313_0_DIAMOND_BOOTS("diamond_boots", null, 313, 0, "items/diamond_boots.png"), + I_314_0_GOLDEN_HELMET("golden_helmet", null, 314, 0, "items/golden_helmet.png"), + I_315_0_GOLDEN_CHESTPLATE("golden_chestplate", null, 315, 0, "items/golden_chestplate.png"), + I_316_0_GOLDEN_LEGGINGS("golden_leggings", null, 316, 0, "items/golden_leggings.png"), + I_317_0_GOLDEN_BOOTS("golden_boots", null, 317, 0, "items/golden_boots.png"), + I_318_0_FLINT("flint", null, 318, 0, "items/flint.png"), + I_319_0_PORKCHOP("porkchop", null, 319, 0, "items/porkchop.png"), + I_320_0_COOKED_PORKCHOP("cooked_porkchop", null, 320, 0, "items/cooked_porkchop.png"), + I_321_0_PAINTING("painting", null, 321, 0, "items/painting.png"), + I_322_0_GOLDEN_APPLE("golden_apple", null, 322, 0, "items/golden_apple.png"), + I_323_0_SIGN("sign", null, 323, 0, "items/sign.png"), + I_324_0_WOODEN_DOOR("wooden_door", null, 324, 0, "items/wooden_door.png"), + I_325_0_BUCKET_BUCKET("bucket", "bucket", 325, 0, "items/bucket_bucket.png"), + I_325_1_BUCKET_MILK("bucket", "milk", 325, 1, "items/bucket_milk.png"), + I_325_8_BUCKET_BUCKET_WATER("bucket", "bucket_water", 325, 8, "items/bucket_bucket_water.png"), + I_325_10_BUCKET_BUCKET_LAVA("bucket", "bucket_lava", 325, 10, "items/bucket_bucket_lava.png"), + I_328_0_MINECART("minecart", null, 328, 0, "items/minecart.png"), + I_329_0_SADDLE("saddle", null, 329, 0, "items/saddle.png"), + I_330_0_IRON_DOOR("iron_door", null, 330, 0, "items/iron_door.png"), + I_331_0_REDSTONE("redstone", null, 331, 0, "items/redstone.png"), + I_332_0_SNOWBALL("snowball", null, 332, 0, "items/snowball.png"), + I_333_0_BOAT_OAK("boat", "oak", 333, 0, "items/boat_oak.png"), + I_333_1_BOAT_SPRUCE("boat", "spruce", 333, 1, "items/boat_spruce.png"), + I_333_2_BOAT_BIRCH("boat", "birch", 333, 2, "items/boat_birch.png"), + I_333_3_BOAT_JUNGLE("boat", "jungle", 333, 3, "items/boat_jungle.png"), + I_333_4_BOAT_ACACIA("boat", "acacia", 333, 4, "items/boat_acacia.png"), + I_333_5_BOAT_BIG_OAK("boat", "big_oak", 333, 5, "items/boat_big_oak.png"), + I_334_0_LEATHER("leather", null, 334, 0, "items/leather.png"), + I_336_0_BRICK("brick", null, 336, 0, "items/brick.png"), + I_337_0_CLAY_BALL("clay_ball", null, 337, 0, "items/clay_ball.png"), + I_338_0_REEDS("reeds", null, 338, 0, "items/reeds.png"), + I_339_0_PAPER("paper", null, 339, 0, "items/paper.png"), + I_340_0_BOOK("book", null, 340, 0, "items/book.png"), + I_341_0_SLIME_BALL("slime_ball", null, 341, 0, "items/slime_ball.png"), + I_342_0_CHEST_MINECART("chest_minecart", null, 342, 0, "items/chest_minecart.png"), + I_344_0_EGG("egg", null, 344, 0, "items/egg.png"), + I_345_0_COMPASS("compass", null, 345, 0, "items/compass.png"), + I_346_0_FISHING_ROD("fishing_rod", null, 346, 0, "items/fishing_rod.png"), + I_347_0_CLOCK("clock", null, 347, 0, "items/clock.png"), + I_348_0_GLOWSTONE_DUST("glowstone_dust", null, 348, 0, "items/glowstone_dust.png"), + I_349_0_FISH("fish", null, 349, 0, "items/fish.png"), + I_350_0_COOKED_FISH("cooked_fish", null, 350, 0, "items/cooked_fish.png"), + I_351_0_DYE_BLACKINKSAC("dye", "black", 351, 0, "items/dye_powder_black.png"), + I_351_1_DYE_RED("dye", "red", 351, 1, "items/dye_powder_red.png"), + I_351_2_DYE_GREEN("dye", "green", 351, 2, "items/dye_powder_green.png"), + I_351_3_DYE_BROWNCOCOABEANS("dye", "brown", 351, 3, "items/dye_powder_brown.png"), + I_351_4_DYE_BLUE("dye", "blue", 351, 4, "items/dye_powder_blue.png"), + I_351_5_DYE_PURPLE("dye", "purple", 351, 5, "items/dye_powder_purple.png"), + I_351_6_DYE_CYAN("dye", "cyan", 351, 6, "items/dye_powder_cyan.png"), + I_351_7_DYE_SILVER("dye", "silver", 351, 7, "items/dye_powder_silver.png"), + I_351_8_DYE_GRAY("dye", "gray", 351, 8, "items/dye_powder_gray.png"), + I_351_9_DYE_PINK("dye", "pink", 351, 9, "items/dye_powder_pink.png"), + I_351_10_DYE_LIME("dye", "lime", 351, 10, "items/dye_powder_lime.png"), + I_351_11_DYE_YELLOW("dye", "yellow", 351, 11, "items/dye_powder_yellow.png"), + I_351_12_DYE_LIGHT_BLUE("dye", "light_blue", 351, 12, "items/dye_powder_light_blue.png"), + I_351_13_DYE_MAGENTA("dye", "magenta", 351, 13, "items/dye_powder_magenta.png"), + I_351_14_DYE_ORANGE("dye", "orange", 351, 14, "items/dye_powder_orange.png"), + I_351_15_DYE_WHITEBONEMEAL("dye", "white", 351, 15, "items/dye_powder_white.png"), + I_352_0_BONE("bone", null, 352, 0, "items/bone.png"), + I_353_0_SUGAR("sugar", null, 353, 0, "items/sugar.png"), + I_354_0_CAKE("cake", null, 354, 0, "items/cake.png"), + I_355_0_BED("bed", null, 355, 0, "items/bed.png"), + I_356_0_REPEATER("repeater", null, 356, 0, "items/repeater.png"), + I_357_0_COOKIE("cookie", null, 357, 0, "items/cookie.png"), + I_358_0_MAP_FILLED("map_filled", null, 358, 0, "items/map_filled.png"), + I_359_0_SHEARS("shears", null, 359, 0, "items/shears.png"), + I_360_0_MELON("melon", null, 360, 0, "items/melon.png"), + I_361_0_PUMPKIN_SEEDS("pumpkin_seeds", null, 361, 0, "items/pumpkin_seeds.png"), + I_362_0_MELON_SEEDS("melon_seeds", null, 362, 0, "items/melon_seeds.png"), + I_363_0_BEEF("beef", null, 363, 0, "items/beef.png"), + I_364_0_COOKED_BEEF("cooked_beef", null, 364, 0, "items/cooked_beef.png"), + I_365_0_CHICKEN("chicken", null, 365, 0, "items/chicken.png"), + I_366_0_COOKED_CHICKEN("cooked_chicken", null, 366, 0, "items/cooked_chicken.png"), + I_367_0_ROTTEN_FLESH("rotten_flesh", null, 367, 0, "items/rotten_flesh.png"), + I_368_0_ENDER_PEARL("ender_pearl", null, 368, 0, "items/ender_pearl.png"), + I_369_0_BLAZE_ROD("blaze_rod", null, 369, 0, "items/blaze_rod.png"), + I_370_0_GHAST_TEAR("ghast_tear", null, 370, 0, "items/ghast_tear.png"), + I_371_0_GOLD_NUGGET("gold_nugget", null, 371, 0, "items/gold_nugget.png"), + I_372_0_NETHER_WART("nether_wart", null, 372, 0, "items/nether_wart.png"), + I_373_0_POTION("potion", null, 373, 0, "items/potion.png"), + I_374_0_GLASS_BOTTLE("glass_bottle", null, 374, 0, "items/glass_bottle.png"), + I_375_0_SPIDER_EYE("spider_eye", null, 375, 0, "items/spider_eye.png"), + I_376_0_FERMENTED_SPIDER_EYE("fermented_spider_eye", null, 376, 0, "items/fermented_spider_eye.png"), + I_377_0_BLAZE_POWDER("blaze_powder", null, 377, 0, "items/blaze_powder.png"), + I_378_0_MAGMA_CREAM("magma_cream", null, 378, 0, "items/magma_cream.png"), + I_379_0_BREWING_STAND("brewing_stand", null, 379, 0, "items/brewing_stand.png"), + I_380_0_CAULDRON("cauldron", null, 380, 0, "items/cauldron.png"), + I_381_0_ENDER_EYE("ender_eye", null, 381, 0, "items/ender_eye.png"), + I_382_0_SPECKLED_MELON("speckled_melon", null, 382, 0, "items/speckled_melon.png"), + I_383_0_SPAWN_EGG("spawn_egg", null, 383, 0, "items/spawn_egg.png"), + I_384_0_EXPERIENCE_BOTTLE("experience_bottle", null, 384, 0, "items/experience_bottle.png"), + I_385_0_FIREBALL("fireball", null, 385, 0, "items/fireball.png"), + I_388_0_EMERALD("emerald", null, 388, 0, "items/emerald.png"), + I_389_0_FRAME("frame", null, 389, 0, "items/frame.png"), + I_390_0_FLOWER_POT("flower_pot", null, 390, 0, "items/flower_pot.png"), + I_391_0_CARROT("carrot", null, 391, 0, "items/carrot.png"), + I_392_0_POTATO("potato", null, 392, 0, "items/potato.png"), + I_393_0_BAKED_POTATO("baked_potato", null, 393, 0, "items/baked_potato.png"), + I_394_0_POISONOUS_POTATO("poisonous_potato", null, 394, 0, "items/poisonous_potato.png"), + I_395_0_EMPTYMAP("emptyMap", null, 395, 0, "items/emptyMap.png"), + I_396_0_GOLDEN_CARROT("golden_carrot", null, 396, 0, "items/golden_carrot.png"), + I_397_0_SKULL_SKELETON("skull", "skeleton", 397, 0, "items/skull_skeleton.png"), + I_397_1_SKULL_WITHER("skull", "wither", 397, 1, "items/skull_wither.png"), + I_397_2_SKULL_ZOMBIE("skull", "zombie", 397, 2, "items/skull_zombie.png"), + I_397_3_SKULL_PLAYER("skull", "player", 397, 3, "items/skull_player.png"), + I_397_4_SKULL_CREEPER("skull", "creeper", 397, 4, "items/skull_creeper.png"), + I_397_5_SKULL_DRAGON("skull", "dragon", 397, 5, "items/skull_dragon.png"), + I_398_0_CARROTONASTICK("carrotOnAStick", null, 398, 0, "items/carrotOnAStick.png"), + I_399_0_NETHERSTAR("netherStar", null, 399, 0, "items/netherStar.png"), + I_400_0_PUMPKIN_PIE("pumpkin_pie", null, 400, 0, "items/pumpkin_pie.png"), + I_403_0_ENCHANTED_BOOK("enchanted_book", null, 403, 0, "items/enchanted_book.png"), + I_404_0_COMPARATOR("comparator", null, 404, 0, "items/comparator.png"), + I_405_0_NETHERBRICK("netherbrick", null, 405, 0, "items/netherbrick.png"), + I_406_0_QUARTZ("quartz", null, 406, 0, "items/quartz.png"), + I_407_0_TNT_MINECART("tnt_minecart", null, 407, 0, "items/tnt_minecart.png"), + I_408_0_HOPPER_MINECART("hopper_minecart", null, 408, 0, "items/hopper_minecart.png"), + I_409_0_PRISMARINE_SHARD("prismarine_shard", null, 409, 0, "items/prismarine_shard.png"), + I_410_0_HOPPER("hopper", null, 410, 0, "items/hopper.png"), + I_411_0_RABBIT("rabbit", null, 411, 0, "items/rabbit.png"), + I_412_0_COOKED_RABBIT("cooked_rabbit", null, 412, 0, "items/cooked_rabbit.png"), + I_413_0_RABBIT_STEW("rabbit_stew", null, 413, 0, "items/rabbit_stew.png"), + I_414_0_RABBIT_FOOT("rabbit_foot", null, 414, 0, "items/rabbit_foot.png"), + I_415_0_RABBIT_HIDE("rabbit_hide", null, 415, 0, "items/rabbit_hide.png"), + I_416_0_HORSEARMORLEATHER("horsearmorleather", null, 416, 0, "items/horsearmorleather.png"), + I_417_0_HORSEARMORIRON("horsearmoriron", null, 417, 0, "items/horsearmoriron.png"), + I_418_0_HORSEARMORGOLD("horsearmorgold", null, 418, 0, "items/horsearmorgold.png"), + I_419_0_HORSEARMORDIAMOND("horsearmordiamond", null, 419, 0, "items/horsearmordiamond.png"), + I_420_0_LEAD("lead", null, 420, 0, "items/lead.png"), + I_421_0_NAMETAG("nameTag", null, 421, 0, "items/nameTag.png"), + I_422_0_PRISMARINE_CRYSTALS("prismarine_crystals", null, 422, 0, "items/prismarine_crystals.png"), + I_423_0_MUTTONRAW("muttonRaw", null, 423, 0, "items/muttonRaw.png"), + I_424_0_MUTTONCOOKED("muttonCooked", null, 424, 0, "items/muttonCooked.png"), + I_426_0_END_CRYSTAL("end_crystal", null, 426, 0, "items/end_crystal.png"), + I_427_0_SPRUCE_DOOR("spruce_door", null, 427, 0, "items/spruce_door.png"), + I_428_0_BIRCH_DOOR("birch_door", null, 428, 0, "items/birch_door.png"), + I_429_0_JUNGLE_DOOR("jungle_door", null, 429, 0, "items/jungle_door.png"), + I_430_0_ACACIA_DOOR("acacia_door", null, 430, 0, "items/acacia_door.png"), + I_431_0_DARK_OAK_DOOR("dark_oak_door", null, 431, 0, "items/dark_oak_door.png"), + I_432_0_CHORUS_FRUIT("chorus_fruit", null, 432, 0, "items/chorus_fruit.png"), + I_433_0_CHORUS_FRUIT_POPPED("chorus_fruit_popped", null, 433, 0, "items/chorus_fruit_popped.png"), + I_437_0_DRAGON_BREATH("dragon_breath", null, 437, 0, "items/dragon_breath.png"), + I_438_0_SPLASH_POTION("splash_potion", null, 438, 0, "items/splash_potion.png"), + I_441_0_LINGERING_POTION("lingering_potion", null, 441, 0, "items/lingering_potion.png"), + I_444_0_ELYTRA("elytra", null, 444, 0, "items/elytra.png"), + I_457_0_BEETROOT("beetroot", null, 457, 0, "items/beetroot.png"), + I_458_0_BEETROOT_SEEDS("beetroot_seeds", null, 458, 0, "items/seeds_beetroot.png"), + I_459_0_BEETROOT_SOUP("beetroot_soup", null, 459, 0, "items/beetroot_soup.png"), + I_460_0_SALMON("salmon", null, 460, 0, "items/fish_salmon.png"), + I_461_0_CLOWNFISH("clownfish", null, 461, 0, "items/fish_clownfish.png"), + I_462_0_PUFFERFISH("pufferfish", null, 462, 0, "items/fish_pufferfish.png"), + I_463_0_COOKED_SALMON("cooked_salmon", null, 463, 0, "items/fish_salmon_cooked.png"), + I_466_0_APPLEENCHANTED("apple_enchanted", null, 466, 0, "items/apple_golden.png"), + I_454_0_BOARD_ONE_BY_ONE("board", "one_by_one", 454, 0, "items/chalkboard_small.png"), + I_454_1_BOARD_TWO_BY_ONE("board", "two_by_one", 454, 1, "items/chalkboard_medium.png"), + I_454_2_BOARD_THREE_BY_TWO("board", "three_by_two", 454, 2, "items/chalkboard_large.png"), + I_456_0_PORTFOLIO("portfolio", null, 456, 0, "items/portfolio.png"), + I_498_0_CAMERA("camera", null, 498, 0, "items/camera.png"); + + private static final Map byDataName = new HashMap<>(); + private static final SparseArray> itemMap; + + static { + itemMap = new SparseArray<>(); + SparseArray subMap; + for (Item b : Item.values()) { + subMap = itemMap.get(b.id); + if (subMap == null) { + subMap = new SparseArray<>(); + itemMap.put(b.id, subMap); + } + subMap.put(b.subId, b); + if (b.subId == 0) byDataName.put(b.str, b); + byDataName.put(b.str + "@" + b.subName, b); + } + } + + public final int id, subId; + public final String str, subName, displayName, identifier; + public final String texPath; + public final ColorWrapper color; + public final boolean hasBiomeShading; + public Bitmap bitmap; + + Item(String name, String subName, int id, int subId, String texPath) { + this.id = id; + this.subId = subId; + this.str = name; + this.subName = subName; + this.displayName = name + " " + subName; + this.texPath = texPath; + this.color = null; + this.hasBiomeShading = false; + this.identifier = "minecraft:" + subName; + } + + public static Item getByDataName(String dataName) { + return byDataName.get(dataName); + } + + public static void loadBitmaps(AssetManager assetManager) throws IOException { + for (Item b : Item.values()) { + if (b.bitmap == null && b.texPath != null) { + try { + b.bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(assetManager.open(b.texPath)), 32, 32, false); + } catch (FileNotFoundException e) { + //TODO file-paths were generated from item names; some do not actually exist... + //Log.w("File not found! "+b.texPath); + } catch (Exception e) { + Log.d(Item.class, e); + } + } + } + } + + public static Item getItem(int id, int meta) { + if (id < 0) return null; + SparseArray subMap = itemMap.get(id); + if (subMap == null) return null; + else return subMap.get(meta); + } + + public static Item getItemWithLegacyId(int id) { + if (id < 0) return null; + SparseArray subMap = itemMap.get(id); + if (subMap == null) return null; + return subMap.valueAt(0); + } + + public static Item getItem(int runtimeId) { + int id = runtimeId >>> 8; + int data = runtimeId & 0xf; + return getItem(id, data); + } + + @Override + public Bitmap getBitmap() { + return this.bitmap; + } + + @NonNull + @Override + public NamedBitmapProvider getNamedBitmapProvider() { + return this; + } + + @NonNull + @Override + public String getBitmapDisplayName() { + return this.displayName; + } + + @NonNull + @Override + public String getBitmapDataName() { + return str + "@" + subName; + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/MCTileProvider.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/MCTileProvider.java index 0dd9dfb4..09b2628b 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/MCTileProvider.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/MCTileProvider.java @@ -10,11 +10,14 @@ import android.text.TextPaint; import com.mithrilmania.blocktopograph.WorldActivityInterface; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.map.renderer.MapType; import com.qozix.tileview.graphics.BitmapProvider; import com.qozix.tileview.tiles.Tile; +import java.lang.ref.WeakReference; + public class MCTileProvider implements BitmapProvider { @@ -27,13 +30,41 @@ public class MCTileProvider implements BitmapProvider { HALF_WORLDSIZE = 1 << 20; public static int worldSizeInBlocks = 2 * HALF_WORLDSIZE, - viewSizeW = worldSizeInBlocks * TILESIZE / Dimension.OVERWORLD.chunkW, - viewSizeL = worldSizeInBlocks * TILESIZE / Dimension.OVERWORLD.chunkL; + viewSizeW = worldSizeInBlocks * TILESIZE / Dimension.OVERWORLD.chunkW, + viewSizeL = worldSizeInBlocks * TILESIZE / Dimension.OVERWORLD.chunkL; - public final WorldActivityInterface worldProvider; + public final WeakReference worldProvider; - public MCTileProvider(WorldActivityInterface worldProvider){ - this.worldProvider = worldProvider; + public MCTileProvider(WorldActivityInterface worldProvider) { + this.worldProvider = new WeakReference<>(worldProvider); + } + + public static Bitmap drawText(String text, Bitmap b, int textColor, int bgColor) { + // Get text dimensions + TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); + textPaint.setStyle(Paint.Style.FILL); + textPaint.setColor(textColor); + textPaint.setTextSize(b.getHeight() / 16f); + StaticLayout mTextLayout = new StaticLayout(text, textPaint, b.getWidth() / 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + + // Create bitmap and canvas to draw to + Canvas c = new Canvas(b); + + if (bgColor != 0) { + // Draw background + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); + paint.setStyle(Paint.Style.FILL); + paint.setColor(bgColor); + c.drawPaint(paint); + } + + // Draw text + c.save(); + c.translate(0, 0); + mTextLayout.draw(c); + c.restore(); + + return b; } @Override @@ -43,14 +74,9 @@ public Bitmap getBitmap(Tile tile, Context context) { try { - - // column and row range from 0 to (worldsize/tilesize) * scale - - Dimension dimension = worldProvider.getDimension(); - // 1 chunk per tile on scale 1.0 - int pixelsPerBlockW_unscaled = TILESIZE / dimension.chunkW; - int pixelsPerBlockL_unscaled = TILESIZE / dimension.chunkL; + int pixelsPerBlockW_unscaled = TILESIZE / 16; + int pixelsPerBlockL_unscaled = TILESIZE / 16; float scale = tile.getDetailLevel().getScale(); @@ -64,27 +90,21 @@ public Bitmap getBitmap(Tile tile, Context context) { // for translating to origin // HALF_WORLDSIZE and TILESIZE must be a power of two - int tilesInHalfWorldW = (HALF_WORLDSIZE * pixelsPerBlockW) / TILESIZE; - int tilesInHalfWorldL = (HALF_WORLDSIZE * pixelsPerBlockL) / TILESIZE; - + int tilesInHalfWorldW = (HALF_WORLDSIZE * pixelsPerBlockW) / TILESIZE; + int tilesInHalfWorldL = (HALF_WORLDSIZE * pixelsPerBlockL) / TILESIZE; // translate tile coord to origin, multiply origin-relative-tile-coordinate with the chunks per tile - int minChunkX = ( tile.getColumn() - tilesInHalfWorldW) * invScale; - int minChunkZ = ( tile.getRow() - tilesInHalfWorldL) * invScale; + int minChunkX = (tile.getColumn() - tilesInHalfWorldW) * invScale; + int minChunkZ = (tile.getRow() - tilesInHalfWorldL) * invScale; int maxChunkX = minChunkX + invScale; int maxChunkZ = minChunkZ + invScale; - - //scale pixels to dimension scale (Nether 1 : 8 Overworld) - pixelsPerBlockW *= dimension.dimensionScale; - pixelsPerBlockL *= dimension.dimensionScale; - - - ChunkManager cm = new ChunkManager(worldProvider.getWorld().getWorldData(), dimension); + WorldActivityInterface worldProvider = this.worldProvider.get(); + Dimension dimension = worldProvider.getDimension(); MapType mapType = (MapType) tile.getDetailLevel().getLevelType(); - if(mapType == null) return null; + if (mapType == null) return null; int x, z, pX, pY; @@ -92,93 +112,65 @@ public Bitmap getBitmap(Tile tile, Context context) { //check if the tile is not aligned with its inner chunks //hacky: it must be a single chunk that is to big for the tile, render just the visible part, easy. - int alignment = invScale % dimension.dimensionScale; - if(alignment > 0){ - - int chunkX = minChunkX / dimension.dimensionScale; - if(minChunkX % dimension.dimensionScale < 0) chunkX -= 1; - int chunkZ = minChunkZ / dimension.dimensionScale; - if(minChunkZ % dimension.dimensionScale < 0) chunkZ -= 1; - - int stepX = dimension.chunkW / dimension.dimensionScale; - int stepZ = dimension.chunkL / dimension.dimensionScale; - int minX = (minChunkX % dimension.dimensionScale) * stepX; - if(minX < 0) minX += dimension.chunkW; - int minZ = (minChunkZ % dimension.dimensionScale) * stepZ; - if(minZ < 0) minZ += dimension.chunkL; - int maxX = (maxChunkX % dimension.dimensionScale) * stepX; - if(maxX <= 0) maxX += dimension.chunkW; - int maxZ = (maxChunkZ % dimension.dimensionScale) * stepZ; - if(maxZ <= 0) maxZ += dimension.chunkL; - - - tileTxt = chunkX+";"+chunkZ+" ("+((chunkX*dimension.chunkW)+minX)+"; "+((chunkZ*dimension.chunkL)+minZ)+")"; - - - mapType.renderer.renderToBitmap(cm, bm, dimension, - chunkX, chunkZ, - minX, minZ , - maxX, maxZ, - 0, 0, - pixelsPerBlockW, pixelsPerBlockL); - - } else { - - minChunkX /= dimension.dimensionScale; - minChunkZ /= dimension.dimensionScale; - maxChunkX /= dimension.dimensionScale; - maxChunkZ /= dimension.dimensionScale; - - tileTxt = "("+(minChunkX*dimension.chunkW)+"; "+(minChunkZ*dimension.chunkL)+")"; - - - int pixelsPerChunkW = pixelsPerBlockW * dimension.chunkW; - int pixelsPerChunkL = pixelsPerBlockL * dimension.chunkL; - - for(z = minChunkZ, pY = 0; z < maxChunkZ; z++, pY += pixelsPerChunkL){ - - for(x = minChunkX, pX = 0; x < maxChunkX; x++, pX += pixelsPerChunkW){ - - try { - mapType.renderer.renderToBitmap(cm, bm, dimension, - x, z, - 0, 0, - dimension.chunkW, dimension.chunkL, - pX, pY, - pixelsPerBlockW, pixelsPerBlockL); - } catch (Exception e){ - MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, - x, z, - 0, 0, - dimension.chunkW, dimension.chunkL, - pX, pY, - pixelsPerBlockW, pixelsPerBlockL); - e.printStackTrace(); - } + + tileTxt = "(" + (minChunkX * 16) + "; " + (minChunkZ * 16) + ")"; + + + int pixelsPerChunkW = pixelsPerBlockW * 16; + int pixelsPerChunkL = pixelsPerBlockL * 16; + + Canvas canvas = new Canvas(bm); + Paint paint = new Paint(); + + WorldData worldData = worldProvider.getWorld().getWorldData(); + + for (z = minChunkZ, pY = 0; z < maxChunkZ; z++, pY += pixelsPerChunkL) + for (x = minChunkX, pX = 0; x < maxChunkX; x++, pX += pixelsPerChunkW) { + + Chunk chunk = worldData.getChunk(x, z, dimension); + if (chunk.isError()) { + MapType.ERROR.renderer.renderToBitmap(chunk, canvas, dimension, + x, z, pX, pY, pixelsPerBlockW, pixelsPerBlockL, paint, worldData); + continue; } + MapType.CHESS.renderer.renderToBitmap(chunk, canvas, dimension, + x, z, pX, pY, pixelsPerBlockW, pixelsPerBlockL, paint, worldData); + if (chunk.isVoid()) continue; + try { + mapType.renderer.renderToBitmap(chunk, canvas, dimension, x, z, + pX, pY, pixelsPerBlockW, pixelsPerBlockL, paint, worldData); + + } catch (Exception e) { + + MapType.ERROR.renderer.renderToBitmap(chunk, canvas, dimension, + x, z, pX, pY, pixelsPerBlockW, pixelsPerBlockL, paint, worldData); + e.printStackTrace(); + + } + } - } //load all those markers with an async task, this task publishes its progress, // the UI thread picks it up and renders the markers - new MarkerAsyncTask(worldProvider, cm, minChunkX, minChunkZ, maxChunkX, maxChunkZ).execute(); + if (worldProvider.getShowMarkers()) + new MarkerAsyncTask(worldProvider, minChunkX, minChunkZ, maxChunkX, maxChunkZ, dimension).execute(); //draw the grid - if(worldProvider.getShowGrid()){ + if (worldProvider.getShowGrid()) { //draw tile-edges white - for(int i = 0; i < TILESIZE; i++){ + for (int i = 0; i < TILESIZE; i++) { //horizontal edges bm.setPixel(i, 0, Color.WHITE); - bm.setPixel(i, TILESIZE-1, Color.WHITE); + bm.setPixel(i, TILESIZE - 1, Color.WHITE); //vertical edges bm.setPixel(0, i, Color.WHITE); - bm.setPixel(TILESIZE-1, i, Color.WHITE); + bm.setPixel(TILESIZE - 1, i, Color.WHITE); } @@ -186,7 +178,7 @@ public Bitmap getBitmap(Tile tile, Context context) { drawText(tileTxt, bm, Color.WHITE, 0); } - } catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } @@ -195,33 +187,4 @@ public Bitmap getBitmap(Tile tile, Context context) { } - public static Bitmap drawText(String text, Bitmap b, int textColor, int bgColor) { - // Get text dimensions - TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); - textPaint.setStyle(Paint.Style.FILL); - textPaint.setColor(textColor); - textPaint.setTextSize(b.getHeight() / 16f); - StaticLayout mTextLayout = new StaticLayout(text, textPaint, b.getWidth() / 2, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - - // Create bitmap and canvas to draw to - Canvas c = new Canvas(b); - - if(bgColor != 0){ - // Draw background - Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); - paint.setStyle(Paint.Style.FILL); - paint.setColor(bgColor); - c.drawPaint(paint); - } - - // Draw text - c.save(); - c.translate(0, 0); - mTextLayout.draw(c); - c.restore(); - - return b; - } - - } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/MapFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/MapFragment.java index 8ab1368f..2c369ef2 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/MapFragment.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/MapFragment.java @@ -1,25 +1,21 @@ package com.mithrilmania.blocktopograph.map; -import android.annotation.SuppressLint; import android.app.Activity; -import android.app.AlertDialog; -import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; import android.os.AsyncTask; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.Snackbar; -import com.mithrilmania.blocktopograph.Log; - -import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.util.DisplayMetrics; +import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.Window; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; @@ -30,22 +26,40 @@ import android.widget.TextView; import android.widget.Toast; -import com.github.clans.fab.FloatingActionButton; -import com.github.clans.fab.FloatingActionMenu; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.UiThread; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.view.ContextThemeWrapper; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; +import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; + +import com.google.android.material.snackbar.Snackbar; +import com.mithrilmania.blocktopograph.Log; import com.mithrilmania.blocktopograph.R; import com.mithrilmania.blocktopograph.World; -import com.mithrilmania.blocktopograph.WorldActivity; import com.mithrilmania.blocktopograph.WorldActivityInterface; -import com.mithrilmania.blocktopograph.WorldData; -import com.mithrilmania.blocktopograph.chunk.*; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.chunk.Chunk; +import com.mithrilmania.blocktopograph.chunk.ChunkTag; +import com.mithrilmania.blocktopograph.chunk.NBTChunkData; +import com.mithrilmania.blocktopograph.databinding.MapFragmentBinding; +import com.mithrilmania.blocktopograph.map.edit.EditFunction; +import com.mithrilmania.blocktopograph.map.edit.RectEditTarget; +import com.mithrilmania.blocktopograph.map.edit.SelectionBasedContextFreeEditTask; +import com.mithrilmania.blocktopograph.map.locator.AdvancedLocatorFragment; import com.mithrilmania.blocktopograph.map.marker.AbstractMarker; import com.mithrilmania.blocktopograph.map.marker.CustomNamedBitmapProvider; import com.mithrilmania.blocktopograph.map.marker.MarkerImageView; +import com.mithrilmania.blocktopograph.map.picer.PicerFragment; import com.mithrilmania.blocktopograph.map.renderer.MapType; +import com.mithrilmania.blocktopograph.map.selection.SelectionMenuFragment; import com.mithrilmania.blocktopograph.nbt.EditableNBT; -import com.mithrilmania.blocktopograph.nbt.convert.DataConverter; -import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; import com.mithrilmania.blocktopograph.nbt.tags.FloatTag; import com.mithrilmania.blocktopograph.nbt.tags.IntTag; @@ -53,17 +67,14 @@ import com.mithrilmania.blocktopograph.nbt.tags.Tag; import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; -import com.mithrilmania.blocktopograph.util.ViewID; import com.mithrilmania.blocktopograph.util.math.DimensionVector3; -import com.qozix.tileview.TileView; import com.qozix.tileview.detail.DetailLevelManager; import com.qozix.tileview.markers.MarkerLayout; import java.io.IOException; +import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -76,39 +87,72 @@ public class MapFragment extends Fragment { - private WorldActivityInterface worldProvider; + private final static int MARKER_INTERVAL_CHECK = 50; + private static final String TAG_PICER = "picer"; + private static final int MARKERS_ON_SCREEN_TOO_MANY = 100; + private static final String PREF_KEY_HAS_NOTIFIED_MARKERS_TOO_MANY = "has_notified_markers_too_many"; + private static final String PREF_KEY_HAS_USED_SELECTION = "hasUsedSelection"; + private static final String KEY_HAS_DOUBLE_TAP = "hasDoubleTap"; + //static, remember choice while app is open. + private static Map markerFilter = new HashMap<>(); - private MCTileProvider minecraftTileProvider; + static { + //entities are enabled by default + for (Entity v : Entity.values()) { + //skip things without a bitmap (dropped items etc.) + //skip entities with placeholder ids (900+) + if (v.sheetPos < 0 || v.id >= 900) continue; + markerFilter.put(v.getNamedBitmapProvider(), + new BitmapChoiceListAdapter.NamedBitmapChoice(v, true)); + } + //tile-entities are disabled by default + for (TileEntity v : TileEntity.values()) { + markerFilter.put(v.getNamedBitmapProvider(), + new BitmapChoiceListAdapter.NamedBitmapChoice(v, false)); + } - private TileView tileView; + } //procedural markers can be iterated while other threads add things to it; // iterating performance is not really affected because of the small size; - public CopyOnWriteArraySet proceduralMarkers = new CopyOnWriteArraySet<>(); + private CopyOnWriteArraySet proceduralMarkers = new CopyOnWriteArraySet<>(); - public Set staticMarkers = new HashSet<>(); - - public AbstractMarker spawnMarker; - public AbstractMarker localPlayerMarker; + private Set staticMarkers = new HashSet<>(); + private AbstractMarker spawnMarker; + private AbstractMarker localPlayerMarker; + private WeakReference worldProvider; + public World world; + private MCTileProvider minecraftTileProvider; + private int proceduralMarkersInterval = 0; + private volatile AsyncTask shrinkProceduralMarkersTask; + /** + * Only one floating fragment is allowed at the same time. + * We use one to display locator. + */ + private Fragment mFloatingFragment; + /** + * Data binding of this fragment view. + */ + private MapFragmentBinding mBinding; @Override public void onPause() { super.onPause(); //pause drawing the map - this.tileView.pause(); + mBinding.tileView.pause(); } @Override public void onStart() { super.onStart(); - - getActivity().setTitle(this.worldProvider.getWorld().getWorldDisplayName()); - - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.MAPFRAGMENT_OPEN); + FragmentActivity activity = getActivity(); + if (activity == null) return; + activity.setTitle(world.getWorldDisplayName()); + Log.logFirebaseEvent(activity, Log.CustomFirebaseEvent.MAPFRAGMENT_OPEN); } @Override @@ -116,9 +160,18 @@ public void onResume() { super.onResume(); //resume drawing the map - this.tileView.resume(); + mBinding.tileView.resume(); + FragmentActivity activity = getActivity(); + if (activity == null) return; + +// Toast toast = new Toast(activity); +// toast.setView(getLayoutInflater().inflate(R.layout.toast_warn, (ViewGroup) activity.getWindow().getDecorView(), false)); +// toast.setDuration(Toast.LENGTH_LONG); +// toast.show(); + } - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.MAPFRAGMENT_RESUME); + public void closeChunks() { + world.getWorldData().resetCache(); } @Override @@ -126,684 +179,450 @@ public void onDestroyView() { super.onDestroyView(); } - - public DimensionVector3 getMultiPlayerPos(String dbKey) throws Exception { - try { - WorldData wData = worldProvider.getWorld().getWorldData(); - wData.openDB(); - byte[] data = wData.db.get(dbKey.getBytes(NBTConstants.CHARSET)); - if(data == null) throw new Exception("no data!"); - final CompoundTag player = (CompoundTag) DataConverter.read(data).get(0); - - ListTag posVec = (ListTag) player.getChildTagByKey("Pos"); - if (posVec == null || posVec.getValue() == null) - throw new Exception("No \"Pos\" specified"); - if (posVec.getValue().size() != 3) - throw new Exception("\"Pos\" value is invalid. value: " + posVec.getValue().toString()); - - IntTag dimensionId = (IntTag) player.getChildTagByKey("DimensionId"); - if(dimensionId == null || dimensionId.getValue() == null) - throw new Exception("No \"DimensionId\" specified"); - Dimension dimension = Dimension.getDimension(dimensionId.getValue()); - if(dimension == null) dimension = Dimension.OVERWORLD; - - return new DimensionVector3<>( - (float) posVec.getValue().get(0).getValue(), - (float) posVec.getValue().get(1).getValue(), - (float) posVec.getValue().get(2).getValue(), - dimension); - - } catch (Exception e) { - Log.e(e.getMessage()); - - Exception e2 = new Exception("Could not find "+dbKey); - e2.setStackTrace(e.getStackTrace()); - throw e2; + private String[] getMarkerTapOptions() { + MarkerTapOption[] values = MarkerTapOption.values(); + int len = values.length; + String[] options = new String[len]; + for (int i = 0; i < len; i++) { + options[i] = getString(values[i].stringId); } + return options; } - public DimensionVector3 getPlayerPos() throws Exception { + /** + * Move map viewer camera to local player's position. + * + *

+ * Triggered by fab click action. + *

+ * + * @param view no use. Yes we pass it to snack maker, but we can just use root view instead. + */ + @UiThread + private void moveCameraToPlayer(View view) { +// if (Math.random() < 2) { +// try { +// Chunk chunk = world.getWorldData().getChunk(0, 0, Dimension.OVERWORLD); +// //byte[] arr = world.getWorldData().getChunkData(0, 0, ChunkTag.TERRAIN, Dimension.OVERWORLD, (byte) 0, true); +// //V1d2d13TerrainSubChunk subChunk = new V1d2d13TerrainSubChunk(ByteBuffer.wrap(arr)); +// for (int z = 0; z < 16; z++) +// chunk.setBlock(0, 6, z, 0, KnownBlockRepr.B_5_0_PLANKS_OAK.getRuntimeId()); +// chunk.save();//world.getWorldData(), 0, 0, Dimension.OVERWORLD, 1); +// Log.d(this, "ok"); +// } catch (Exception e) { +// Log.d(this, e); +// } +// return; +// } try { - WorldData wData = worldProvider.getWorld().getWorldData(); - wData.openDB(); - byte[] data = wData.db.get(World.SpecialDBEntryType.LOCAL_PLAYER.keyBytes); - final CompoundTag player = data != null - ? (CompoundTag) DataConverter.read(data).get(0) - : (CompoundTag) worldProvider.getWorld().level.getChildTagByKey("Player"); + Activity activity = getActivity(); + if (activity == null) return; - ListTag posVec = (ListTag) player.getChildTagByKey("Pos"); - if (posVec == null || posVec.getValue() == null) - throw new Exception("No \"Pos\" specified"); - if (posVec.getValue().size() != 3) - throw new Exception("\"Pos\" value is invalid. value: " + posVec.getValue().toString()); + DimensionVector3 playerPos = world.getPlayerPos(); - IntTag dimensionId = (IntTag) player.getChildTagByKey("DimensionId"); - if(dimensionId == null || dimensionId.getValue() == null) - throw new Exception("No \"DimensionId\" specified"); - Dimension dimension = Dimension.getDimension(dimensionId.getValue()); - if(dimension == null) dimension = Dimension.OVERWORLD; + assert playerPos != null; + Snackbar.make(mBinding.tileView, + getString(R.string.something_at_xyz_dim_float, getString(R.string.player), + playerPos.x, playerPos.y, playerPos.z), + Snackbar.LENGTH_SHORT) + .setAction("Action", null).show(); - return new DimensionVector3<>( - (float) posVec.getValue().get(0).getValue(), - (float) posVec.getValue().get(1).getValue(), - (float) posVec.getValue().get(2).getValue(), - dimension); + WorldActivityInterface worldProvider = this.worldProvider.get(); + if (playerPos.dimension != worldProvider.getDimension()) { + worldProvider.changeMapType(playerPos.dimension.defaultMapType, playerPos.dimension); + } + Log.logFirebaseEvent(activity, Log.CustomFirebaseEvent.GPS_LOCATE); - } catch (Exception e) { - Log.e(e.toString()); + frameTo((double) playerPos.x, (double) playerPos.z); - Exception e2 = new Exception("Could not find player."); - e2.setStackTrace(e.getStackTrace()); - throw e2; + } catch (Exception e) { + Log.d(this, e); + Snackbar.make(view, R.string.failed_find_player, Snackbar.LENGTH_LONG) + .show(); } } - public DimensionVector3 getSpawnPos() throws Exception { + /** + * Move map viewer camera to world spawn position. + * + *

+ * Triggered by fab click action. + *

+ * + * @param view no use. Yes we pass it to snack maker, but we can just use root view instead. + */ + @UiThread + private void moveCameraToSpawn(View view) { try { - CompoundTag level = this.worldProvider.getWorld().level; - int spawnX = ((IntTag) level.getChildTagByKey("SpawnX")).getValue(); - int spawnY = ((IntTag) level.getChildTagByKey("SpawnY")).getValue(); - int spawnZ = ((IntTag) level.getChildTagByKey("SpawnZ")).getValue(); - if(spawnY == 256){ - TerrainChunkData data = new ChunkManager( - this.worldProvider.getWorld().getWorldData(), Dimension.OVERWORLD) - .getChunk(spawnX >> 4, spawnZ >> 4) - .getTerrain((byte) 0); - if(data.load2DData()) spawnY = data.getHeightMapValue(spawnX % 16, spawnZ % 16) + 1; - } - return new DimensionVector3<>( spawnX, spawnY, spawnZ, Dimension.OVERWORLD); - } catch (Exception e){ - throw new Exception("Could not find spawn"); - } - } - - public static class MarkerListAdapter extends ArrayAdapter { - - MarkerListAdapter(Context context, List objects) { - super(context, 0, objects); - } + Activity activity = getActivity(); + if (activity == null) return; - @NonNull - @Override - public View getView(int position, View convertView, @NonNull ViewGroup parent) { + DimensionVector3 spawnPos = world.getSpawnPos(); - RelativeLayout v = (RelativeLayout) convertView; + Snackbar.make(mBinding.tileView, + getString(R.string.something_at_xyz_dim_int, getString(R.string.spawn), + spawnPos.x, spawnPos.y, spawnPos.z), + Snackbar.LENGTH_SHORT) + .setAction("Action", null).show(); - if (v == null) { - LayoutInflater vi; - vi = LayoutInflater.from(getContext()); - v = (RelativeLayout) vi.inflate(R.layout.marker_list_entry, parent, false); + WorldActivityInterface worldProvider = MapFragment.this.worldProvider.get(); + if (spawnPos.dimension != worldProvider.getDimension()) { + worldProvider.changeMapType(spawnPos.dimension.defaultMapType, spawnPos.dimension); } - AbstractMarker m = getItem(position); - - if (m != null) { - TextView name = (TextView) v.findViewById(R.id.marker_name); - TextView xz = (TextView) v.findViewById(R.id.marker_xz); - ImageView icon = (ImageView) v.findViewById(R.id.marker_icon); - - name.setText(m.getNamedBitmapProvider().getBitmapDisplayName()); - String xzStr = String.format(Locale.ENGLISH, "x: %d, y: %d, z: %d", m.x, m.y, m.z); - xz.setText(xzStr); - - m.loadIcon(icon); + Log.logFirebaseEvent(activity, Log.CustomFirebaseEvent.GPS_LOCATE); - } + frameTo((double) spawnPos.x, (double) spawnPos.z); - return v; + } catch (Exception e) { + e.printStackTrace(); + Snackbar.make(view, R.string.failed_find_spawn, Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); } - } - public enum MarkerTapOption { + /** + * Callback to close the ongoing floating pane. + */ + @UiThread + private void closeFloatPane() { + if (mFloatingFragment != null) { + FragmentManager fm = getChildFragmentManager(); + FragmentTransaction trans = fm.beginTransaction(); + trans.remove(mFloatingFragment); + + // If in selection mode, recover selection menu. + if (mBinding.selectionBoard.hasSelection()) { + SelectionMenuFragment fragment = SelectionMenuFragment + .newInstance(mBinding.selectionBoard.getSelection(), + world.getWorldData().mOldBlockRegistry, this::doSelectionBasedEdit); + trans.add(R.id.float_window_container, fragment); + mFloatingFragment = fragment; + setUpSelectionMenu(); + } else mFloatingFragment = null; + + trans.commit(); + } + } - TELEPORT_LOCAL_PLAYER(R.string.teleport_local_player), - REMOVE_MARKER(R.string.remove_custom_marker); + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (mFloatingFragment != null) { + FloatPaneFragment fragment; + if (mFloatingFragment instanceof AdvancedLocatorFragment) { + fragment = AdvancedLocatorFragment.create(world, this::frameTo); + } else if (mFloatingFragment instanceof SelectionMenuFragment) { + fragment = SelectionMenuFragment + .newInstance(mBinding.selectionBoard.getSelection(), world.getWorldData().mOldBlockRegistry, + this::doSelectionBasedEdit); + } else return; + closeFloatPane(); + openFloatPane(fragment); + setUpSelectionMenu(); + } + } - public final int stringId; + /** + * Set up selection menu and connect it with selection board. + * + *

+ * Called when selection mode begins, or when another float pane that used to be opened and + * replaced selection menu, we have to recover selection menu when the pane was dead. + *

+ */ + private void setUpSelectionMenu() { + if (mFloatingFragment instanceof SelectionMenuFragment) { + SelectionMenuFragment fragment = (SelectionMenuFragment) mFloatingFragment; + mBinding.selectionBoard.setSelectionChangedListener(fragment::onSelectionChangedOutsides); + fragment.setSelectionChangedListener(mBinding.selectionBoard::onSelectionChangedOutsides); + } + } - MarkerTapOption(int id){ - this.stringId = id; + /** + * When another float pane was opened and replaced selection menu, we disconnect selection + * menu and selection board. + */ + private void unsetSelectionMenu() { + if (mFloatingFragment instanceof SelectionMenuFragment) { + SelectionMenuFragment fragment = (SelectionMenuFragment) mFloatingFragment; + fragment.setSelectionChangedListener(null); } + mBinding.selectionBoard.setSelectionChangedListener(null); + } + /** + * Show a floating pane fragment. Will remove already existing one. + * + * @param fragment pane fragment to be attached. + */ + @UiThread + private void openFloatPane(@NonNull FloatPaneFragment fragment) { + FragmentManager fm = getChildFragmentManager(); + fragment.setOnCloseButtonClickListener(this::closeFloatPane); + FragmentTransaction trans = fm.beginTransaction(); + // Remove existing float pane. + if (mFloatingFragment instanceof SelectionMenuFragment) unsetSelectionMenu(); + if (mFloatingFragment != null) trans.remove(mFloatingFragment); + trans.add(R.id.float_window_container, fragment).commit(); + mFloatingFragment = fragment; } - public String[] getMarkerTapOptions(){ - MarkerTapOption[] values = MarkerTapOption.values(); - int len = values.length; - String[] options = new String[len]; - for(int i = 0; i < len; i++){ - options[i] = getString(values[i].stringId); + private void onOpenFab(View view) { + if (mBinding.fabMenu.isOpened()) + mBinding.fabMenu.close(true); + else { + mBinding.fabMenu.open(true); + FragmentActivity activity = getActivity(); + if (activity != null) { + SharedPreferences preferences = activity.getPreferences(Context.MODE_PRIVATE); + if (!preferences + .getBoolean(KEY_HAS_DOUBLE_TAP, false)) { + Toast.makeText(activity, getString(R.string.map_dblclick_notice), Toast.LENGTH_SHORT).show(); + preferences.edit().putBoolean(KEY_HAS_DOUBLE_TAP, true).apply(); + } + } } - return options; } @Nullable @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //TODO handle savedInstance... - - View rootView = inflater.inflate(R.layout.map_fragment, container, false); - RelativeLayout worldContainer = (RelativeLayout) rootView.findViewById(R.id.world_tileview_container); - assert worldContainer != null; - - /* - GPS button: moves camera to player position - */ - FloatingActionButton fabGPSPlayer = (FloatingActionButton) rootView.findViewById(R.id.fab_menu_gps_player); - assert fabGPSPlayer != null; - fabGPSPlayer.setOnClickListener(new View.OnClickListener() { + mBinding = DataBindingUtil.inflate( + inflater, R.layout.map_fragment, container, false); + mBinding.tileView.setSelectionView(mBinding.selectionBoard); + mBinding.selectionBoard.setTileView(mBinding.tileView); + mBinding.tileView.setOuterDoubleTapListener(new GestureDetector.OnDoubleTapListener() { @Override - public void onClick(View view) { - try { - if(tileView == null) throw new Exception("No map available."); - - DimensionVector3 playerPos = getPlayerPos(); - - Snackbar.make(tileView, - getString(R.string.something_at_xyz_dim_float, getString(R.string.player), - playerPos.x, playerPos.y, playerPos.z, playerPos.dimension.name), - Snackbar.LENGTH_SHORT) - .setAction("Action", null).show(); - - if(playerPos.dimension != worldProvider.getDimension()){ - worldProvider.changeMapType(playerPos.dimension.defaultMapType, playerPos.dimension); - } - - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.GPS_PLAYER); - - frameTo((double) playerPos.x, (double) playerPos.z); - - } catch (Exception e){ - e.printStackTrace(); - Snackbar.make(view, R.string.failed_find_player, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } + public boolean onSingleTapConfirmed(MotionEvent e) { + return false; } - }); - /* - GPS button: moves camera to spawn - */ - FloatingActionButton fabGPSSpawn = (FloatingActionButton) rootView.findViewById(R.id.fab_menu_gps_spawn); - assert fabGPSSpawn != null; - fabGPSSpawn.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { - try { - DimensionVector3 spawnPos = getSpawnPos(); - - Snackbar.make(tileView, - getString(R.string.something_at_xyz_dim_int, getString(R.string.spawn), - spawnPos.x, spawnPos.y, spawnPos.z, spawnPos.dimension.name), - Snackbar.LENGTH_SHORT) - .setAction("Action", null).show(); - - if(spawnPos.dimension != worldProvider.getDimension()){ - worldProvider.changeMapType(spawnPos.dimension.defaultMapType, spawnPos.dimension); - } - - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.GPS_SPAWN); - - frameTo((double) spawnPos.x, (double) spawnPos.z); + public boolean onDoubleTap(MotionEvent e) { + worldProvider.get().openDrawer(); + FragmentActivity activity = getActivity(); + if (activity != null) + activity.getPreferences(Context.MODE_PRIVATE) + .edit().putBoolean(KEY_HAS_DOUBLE_TAP, true).apply(); + return false; + } - } catch (Exception e){ - e.printStackTrace(); - Snackbar.make(view, R.string.failed_find_spawn, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } + @Override + public boolean onDoubleTapEvent(MotionEvent e) { + return false; } }); - final Activity activity = getActivity(); - if(activity == null){ - new Exception("MapFragment: activity is null, cannot set worldProvider!").printStackTrace(); + if (activity == null) { + Log.e(this, new Exception("MapFragment: activity is null, cannot set worldProvider!")); return null; } - try { - //noinspection ConstantConditions - worldProvider = (WorldActivityInterface) activity; - } catch (ClassCastException e){ - new Exception("MapFragment: activity is not an worldprovider, cannot set worldProvider!", e).printStackTrace(); - return null; - } - - //show the toolbar if the fab menu is opened - FloatingActionMenu fabMenu = (FloatingActionMenu) rootView.findViewById(R.id.fab_menu); - fabMenu.setOnMenuToggleListener(new FloatingActionMenu.OnMenuToggleListener() { - @Override - public void onMenuToggle(boolean opened) { - if(opened) worldProvider.showActionBar(); - else worldProvider.hideActionBar(); - } + WorldActivityInterface activityInterface = (WorldActivityInterface) activity; + worldProvider = new WeakReference<>(activityInterface); + world = activityInterface.getWorld(); + + mBinding.fabMenu.setOnMenuButtonClickListener(this::onOpenFab); + + // GPS button: moves camera to player position + mBinding.fabMenuGpsPlayer.setOnClickListener(this::moveCameraToPlayer); + Resources resources = activity.getResources(); + mBinding.fabMenuGpsPlayer.setImageDrawable( + VectorDrawableCompat.create(resources, R.drawable.ic_person, null)); + + // GPS button: moves camera to spawn + mBinding.fabMenuGpsSpawn.setOnClickListener(this::moveCameraToSpawn); + mBinding.fabMenuGpsSpawn.setImageDrawable( + VectorDrawableCompat.create(resources, R.drawable.ic_action_home, null)); + + // Display a menu allowing user to move camera to many places. + mBinding.fabMenuGpsOthers.setOnClickListener(unusedView -> + openFloatPane(AdvancedLocatorFragment.create(world, this::frameTo))); + mBinding.fabMenuGpsOthers.setImageDrawable( + VectorDrawableCompat.create(resources, R.drawable.ic_action_search, null)); + + mBinding.fabMenuGpsPicer.setOnClickListener(unusedView -> { + WorldActivityInterface worldProvider = this.worldProvider.get(); + if (worldProvider == null) return; + DialogFragment fragment = PicerFragment.create(world, + worldProvider.getDimension(), null, this::triggerLongPressAtCenter); + fragment.show(getChildFragmentManager(), TAG_PICER); + }); + mBinding.fabMenuGpsPicer.setImageDrawable( + VectorDrawableCompat.create(resources, R.drawable.ic_menu_camera, null)); + + // Show the toolbar if the fab menu is opened + mBinding.fabMenu.setOnMenuToggleListener(opened -> { + WorldActivityInterface worldProvider = MapFragment.this.worldProvider.get(); + if (opened) { + worldProvider.showActionBar(); + //worldProvider.openDrawer(); + } else worldProvider.hideActionBar(); }); + try { + Entity.loadEntityBitmaps(activity.getAssets()); + } catch (IOException e) { + Log.d(this, e); + } - FloatingActionButton fabGPSMarker = (FloatingActionButton) rootView.findViewById(R.id.fab_menu_gps_marker); - assert fabGPSMarker != null; - fabGPSMarker.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - Collection markers = worldProvider.getWorld().getMarkerManager().getMarkers(); - - if(markers.isEmpty()){ - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - TextView msg = new TextView(activity); - float dpi = activity.getResources().getDisplayMetrics().density; - msg.setPadding((int)(19*dpi), (int)(5*dpi), (int)(14*dpi), (int)(5*dpi)); - msg.setMaxLines(20); - msg.setText(R.string.no_custom_markers); - builder.setView(msg) - .setTitle(R.string.no_custom_markers_title) - .setCancelable(true) - .setNeutralButton(android.R.string.ok, null) - .show(); - } else { - - AlertDialog.Builder markerDialogBuilder = new AlertDialog.Builder(activity); - markerDialogBuilder.setIcon(R.drawable.ic_place); - markerDialogBuilder.setTitle(R.string.go_to_a_marker_list); - - final MarkerListAdapter arrayAdapter = new MarkerListAdapter(activity, new ArrayList<>(markers)); - - markerDialogBuilder.setNegativeButton(android.R.string.cancel, null); - - markerDialogBuilder.setAdapter( - arrayAdapter, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - AbstractMarker m = arrayAdapter.getItem(which); - if(m == null) return; - - Snackbar.make(tileView, - activity.getString(R.string.something_at_xyz_dim_int, - m.getNamedBitmapProvider().getBitmapDisplayName(), - m.x, m.y, m.z, m.dimension.name), - Snackbar.LENGTH_SHORT) - .setAction("Action", null).show(); - - if(m.dimension != worldProvider.getDimension()){ - worldProvider.changeMapType(m.dimension.defaultMapType, m.dimension); - } - - frameTo((double) m.x, (double) m.z); - - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.GPS_MARKER); - } - }); - markerDialogBuilder.show(); - } + try { + KnownBlockRepr.loadBitmaps(activity.getAssets()); + } catch (IOException e) { + Log.d(this, e); + } + try { + CustomIcon.loadCustomBitmaps(activity.getAssets()); + } catch (IOException e) { + Log.d(this, e); + } - } catch (Exception e){ - Snackbar.make(view, e.getMessage(), Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - } - }); + //set the map-type + MapTileView tileView = mBinding.tileView; + tileView.getDetailLevelManager().setLevelType(worldProvider.get().getMapType()); + tileView.setOnLongPressListener(this::onLongPressed); /* - GPS button: moves camera to player position + Create tile(=bitmap) provider */ - FloatingActionButton fabGPSMultiplayer = (FloatingActionButton) rootView.findViewById(R.id.fab_menu_gps_multiplayer); - assert fabGPSMultiplayer != null; - fabGPSMultiplayer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(final View view) { - - if (tileView == null){ - Snackbar.make(view, R.string.no_map_available, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - return; - } + this.minecraftTileProvider = new MCTileProvider(worldProvider.get()); - Snackbar.make(tileView, - R.string.searching_for_players, - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - //this can take some time... ...do it in the background - (new AsyncTask(){ - @Override - protected String[] doInBackground(Void... arg0) { - try { - return worldProvider.getWorld().getWorldData().getPlayers(); - } catch (Exception e){ - return null; - } - } + /* + Set the bitmap-provider of the tile view + */ + tileView.setBitmapProvider(this.minecraftTileProvider); - protected void onPostExecute(final String[] players) { - getActivity().runOnUiThread(new Runnable() { - @Override - public void run() { - if(players == null){ - Snackbar.make(view, R.string.failed_to_retrieve_player_data, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - return; - } + /* + Change tile view settings + */ - if(players.length == 0){ - Snackbar.make(view, R.string.no_multiplayer_data_found, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - return; - } + tileView.setBackgroundColor(0xFF494E8E); + // markers should align to the coordinate along the horizontal center and vertical bottom + tileView.setMarkerAnchorPoints(-0.5f, -1.0f); + tileView.defineBounds( + -1.0, + -1.0, + 1.0, + 1.0 + ); - //NBT tag type spinner - final Spinner spinner = new Spinner(activity); - ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(activity, - android.R.layout.simple_spinner_item, players); + tileView.setSize(MCTileProvider.viewSizeW, MCTileProvider.viewSizeL); - spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(spinnerArrayAdapter); + for (MapType mapType : MapType.values()) { + tileView.addDetailLevel(0.0625f, "0.0625", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType);// 1/(1/16)=16 chunks per tile + tileView.addDetailLevel(0.125f, "0.125", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType); + tileView.addDetailLevel(0.25f, "0.25", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType); + tileView.addDetailLevel(0.5f, "0.5", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType); + tileView.addDetailLevel(1f, "1", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType);// 1/1=1 chunk per tile + } + tileView.setScale(0.5f); + + // Notify user to try using selection. + if (!activity.getPreferences(Context.MODE_PRIVATE).getBoolean(PREF_KEY_HAS_USED_SELECTION, false)) { + if (System.currentTimeMillis() % 25 == 0) tileView.postDelayed(() -> { + FragmentActivity activity1 = getActivity(); + if (activity1 == null) return; + new AlertDialog.Builder(activity1) + .setMessage(R.string.map_notice_try_selection) + .setPositiveButton(android.R.string.ok, null) + .create() + .show(); + activity1.getPreferences(Context.MODE_PRIVATE) + .edit() + .putBoolean(PREF_KEY_HAS_USED_SELECTION, true) + .apply(); + }, 1000); + } - //wrap layout in alert - new AlertDialog.Builder(activity) - .setTitle(R.string.go_to_player) - .setView(spinner) - .setPositiveButton(R.string.go_loud, new DialogInterface.OnClickListener() { + boolean framedToPlayer = false; - public void onClick(DialogInterface dialog, int whichButton) { + //TODO multi-thread this + try { - //new tag type - int spinnerIndex = spinner.getSelectedItemPosition(); - String playerKey = players[spinnerIndex]; + DimensionVector3 playerPos = world.getPlayerPos(); + float x = playerPos.x, y = playerPos.y, z = playerPos.z; + Log.d(this, "Placed player marker at: " + x + ";" + y + ";" + z + " [" + playerPos.dimension.name + "]"); + localPlayerMarker = new AbstractMarker((int) x, (int) y, (int) z, + playerPos.dimension, new CustomNamedBitmapProvider(Entity.PLAYER, "~local_player"), false); + this.staticMarkers.add(localPlayerMarker); + addMarker(localPlayerMarker); - try { - DimensionVector3 playerPos = getMultiPlayerPos(playerKey); + WorldActivityInterface worldProvider = this.worldProvider.get(); + if (localPlayerMarker.dimension != worldProvider.getDimension()) { + worldProvider.changeMapType(localPlayerMarker.dimension.defaultMapType, localPlayerMarker.dimension); + } - Snackbar.make(tileView, - getString(R.string.something_at_xyz_dim_float, - playerKey, - playerPos.x, - playerPos.y, - playerPos.z, - playerPos.dimension.name), - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); + frameTo((double) x, (double) z); + framedToPlayer = true; - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.GPS_MULTIPLAYER); + } catch (Exception e) { + e.printStackTrace(); + Log.d(this, "Failed to place player marker. " + e.toString()); + } - if(playerPos.dimension != worldProvider.getDimension()){ - worldProvider.changeMapType(playerPos.dimension.defaultMapType, playerPos.dimension); - } - frameTo((double) playerPos.x, (double) playerPos.z); + try { + DimensionVector3 spawnPos = world.getSpawnPos(); - } catch (Exception e){ - Snackbar.make(view, e.getMessage(), Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } + spawnMarker = new AbstractMarker(spawnPos.x, spawnPos.y, spawnPos.z, spawnPos.dimension, + new CustomNamedBitmapProvider(CustomIcon.SPAWN_MARKER, "Spawn"), false); + this.staticMarkers.add(spawnMarker); + addMarker(spawnMarker); - } - }) - //or alert is cancelled - .setNegativeButton(android.R.string.cancel, null) - .show(); - } - }); - } + if (!framedToPlayer) { - }).execute(); + WorldActivityInterface worldProvider = this.worldProvider.get(); + if (spawnMarker.dimension != worldProvider.getDimension()) { + worldProvider.changeMapType(spawnMarker.dimension.defaultMapType, spawnMarker.dimension); + } + frameTo((double) spawnPos.x, (double) spawnPos.z); } - }); + } catch (Exception e) { + //no spawn defined... + if (!framedToPlayer) frameTo(0.0, 0.0); - /* - GPS button: moves camera to player position - */ - FloatingActionButton fabGPSCoord = (FloatingActionButton) rootView.findViewById(R.id.fab_menu_gps_coord); - assert fabGPSCoord != null; - fabGPSCoord.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - if(tileView == null) throw new Exception("No map available."); - - View xzForm = LayoutInflater.from(activity).inflate(R.layout.xz_coord_form, null); - final EditText xInput = (EditText) xzForm.findViewById(R.id.x_input); - xInput.setText("0"); - final EditText zInput = (EditText) xzForm.findViewById(R.id.z_input); - zInput.setText("0"); - - //wrap layout in alert - new AlertDialog.Builder(activity) - .setTitle(R.string.go_to_coordinate) - .setView(xzForm) - .setPositiveButton(R.string.go_loud, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { + } - int inX, inZ; - try{ - inX = Integer.parseInt(xInput.getText().toString()); - } catch (NullPointerException | NumberFormatException e){ - Toast.makeText(activity, R.string.invalid_x_coordinate,Toast.LENGTH_LONG).show(); - return; - } - try{ - inZ = Integer.parseInt(zInput.getText().toString()); - } catch (NullPointerException | NumberFormatException e){ - Toast.makeText(activity, R.string.invalid_z_coordinate,Toast.LENGTH_LONG).show(); - return; - } - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.GPS_COORD); - - frameTo((double) inX, (double) inZ); - } - }) - .setCancelable(true) - .setNegativeButton(android.R.string.cancel, null) - .show(); - - } catch (Exception e){ - Snackbar.make(view, e.getMessage(), Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - } - }); - - - - try { - Entity.loadEntityBitmaps(activity.getAssets()); - } catch (IOException e) { - e.printStackTrace(); - } - - try { - Block.loadBitmaps(activity.getAssets()); - } catch (IOException e) { - e.printStackTrace(); - } - try{ - CustomIcon.loadCustomBitmaps(activity.getAssets()); - } catch (IOException e){ - e.printStackTrace(); - } - - - - - /* - Create tile view - */ - this.tileView = new TileView(activity) { - - @Override - public void onLongPress(MotionEvent event) { - - Dimension dimension = worldProvider.getDimension(); - - // 1 chunk per tile on scale 1.0 - int pixelsPerBlockW_unscaled = MCTileProvider.TILESIZE / dimension.chunkW; - int pixelsPerBlockL_unscaled = MCTileProvider.TILESIZE / dimension.chunkL; - - float pixelsPerBlockScaledW = pixelsPerBlockW_unscaled * this.getScale(); - float pixelsPerBlockScaledL = pixelsPerBlockL_unscaled * this.getScale(); - - - double worldX = ((( this.getScrollX() + event.getX()) / pixelsPerBlockScaledW) - MCTileProvider.HALF_WORLDSIZE) / dimension.dimensionScale; - double worldZ = ((( this.getScrollY() + event.getY()) / pixelsPerBlockScaledL) - MCTileProvider.HALF_WORLDSIZE) / dimension.dimensionScale; - - MapFragment.this.onLongClick(worldX, worldZ); - } - }; - - this.tileView.setId(ViewID.generateViewId()); - - //set the map-type - tileView.getDetailLevelManager().setLevelType(worldProvider.getMapType()); - - /* - Add tile view to main layout - */ - - //add world view to its container in the main layout - worldContainer.addView(tileView); - - - /* - Create tile(=bitmap) provider - */ - this.minecraftTileProvider = new MCTileProvider(worldProvider); - - - - /* - Set the bitmap-provider of the tile view - */ - this.tileView.setBitmapProvider(this.minecraftTileProvider); - - - /* - Change tile view settings - */ - - this.tileView.setBackgroundColor(0xFF494E8E); - - // markers should align to the coordinate along the horizontal center and vertical bottom - tileView.setMarkerAnchorPoints(-0.5f, -1.0f); - - this.tileView.defineBounds( - -1.0, - -1.0, - 1.0, - 1.0 - ); - - this.tileView.setSize(MCTileProvider.viewSizeW, MCTileProvider.viewSizeL); - - for(MapType mapType : MapType.values()){ - this.tileView.addDetailLevel(0.0625f, "0.0625", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType);// 1/(1/16)=16 chunks per tile - this.tileView.addDetailLevel(0.125f, "0.125", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType); - this.tileView.addDetailLevel(0.25f, "0.25", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType); - this.tileView.addDetailLevel(0.5f, "0.5", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType); - this.tileView.addDetailLevel(1f, "1", MCTileProvider.TILESIZE, MCTileProvider.TILESIZE, mapType);// 1/1=1 chunk per tile - - } - - this.tileView.setScale(0.5f); - - - boolean framedToPlayer = false; - - //TODO multi-thread this - try { - - DimensionVector3 playerPos = getPlayerPos(); - float x = playerPos.x, y = playerPos.y, z = playerPos.z; - Log.d("Placed player marker at: "+x+";"+y+";"+z+" ["+playerPos.dimension.name+"]"); - localPlayerMarker = new AbstractMarker((int) x, (int) y, (int) z, - playerPos.dimension, new CustomNamedBitmapProvider(Entity.PLAYER, "~local_player"), false); - this.staticMarkers.add(localPlayerMarker); - addMarker(localPlayerMarker); - - if(localPlayerMarker.dimension != worldProvider.getDimension()){ - worldProvider.changeMapType(localPlayerMarker.dimension.defaultMapType, localPlayerMarker.dimension); - } - - frameTo((double) x, (double) z); - framedToPlayer = true; - - } catch (Exception e){ - e.printStackTrace(); - Log.d("Failed to place player marker. "+e.toString()); - } - - - try { - DimensionVector3 spawnPos = getSpawnPos(); - - spawnMarker = new AbstractMarker(spawnPos.x, spawnPos.y, spawnPos.z, spawnPos.dimension, - new CustomNamedBitmapProvider(CustomIcon.SPAWN_MARKER, "Spawn"), false); - this.staticMarkers.add(spawnMarker); - addMarker(spawnMarker); - - if(!framedToPlayer){ - - if(spawnMarker.dimension != worldProvider.getDimension()){ - worldProvider.changeMapType(spawnMarker.dimension.defaultMapType, spawnMarker.dimension); - } - - frameTo((double) spawnPos.x, (double) spawnPos.z); - } - - } catch (Exception e){ - //no spawn defined... - if(!framedToPlayer) frameTo(0.0, 0.0); - - } - - - - - - - tileView.getMarkerLayout().setMarkerTapListener(new MarkerLayout.MarkerTapListener() { - @Override - public void onMarkerTap(View view, int tapX, int tapY) { - if(!(view instanceof MarkerImageView)){ - Log.d("Markertaplistener found a marker that is not a MarkerImageView! "+view.toString()); - return; - } + tileView.getMarkerLayout().setMarkerTapListener(new MarkerLayout.MarkerTapListener() { + @Override + public void onMarkerTap(View view, int tapX, int tapY) { + if (!(view instanceof MarkerImageView)) return; final AbstractMarker marker = ((MarkerImageView) view).getMarkerHook(); - if(marker == null){ - Log.d("abstract marker is null! "+view.toString()); - return; - } + if (marker == null) return; AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder - .setTitle(String.format(getString(R.string.marker_info), marker.getNamedBitmapProvider().getBitmapDisplayName(), marker.getNamedBitmapProvider().getBitmapDataName(), marker.x, marker.y, marker.z, marker.dimension)) + .setTitle(String.format(getString(R.string.marker_info), marker.getNamedBitmapProvider().getBitmapDisplayName(), marker.x, marker.y, marker.z)) .setItems(getMarkerTapOptions(), new DialogInterface.OnClickListener() { @SuppressWarnings("RedundantCast") - @SuppressLint("SetTextI18n") public void onClick(DialogInterface dialog, int which) { final MarkerTapOption chosen = MarkerTapOption.values()[which]; - switch (chosen){ + switch (chosen) { case TELEPORT_LOCAL_PLAYER: { try { - final EditableNBT playerEditable = worldProvider.getEditablePlayer(); + final EditableNBT playerEditable = worldProvider.get().getEditablePlayer(); if (playerEditable == null) throw new Exception("Player is null"); @@ -816,7 +635,8 @@ public void onClick(DialogInterface dialog, int which) { ListTag posVec = (ListTag) playerTag.getChildTagByKey("Pos"); - if (posVec == null) throw new Exception("No \"Pos\" specified"); + if (posVec == null) + throw new Exception("No \"Pos\" specified"); final List playerPos = posVec.getValue(); if (playerPos == null) @@ -825,7 +645,7 @@ public void onClick(DialogInterface dialog, int which) { throw new Exception("\"Pos\" value is invalid. value: " + posVec.getValue().toString()); IntTag dimensionId = (IntTag) playerTag.getChildTagByKey("DimensionId"); - if(dimensionId == null || dimensionId.getValue() == null) + if (dimensionId == null || dimensionId.getValue() == null) throw new Exception("No \"DimensionId\" specified"); @@ -840,38 +660,38 @@ public void onClick(DialogInterface dialog, int which) { dimensionId.setValue(newDimension.id); - if(playerEditable.save()){ + if (playerEditable.save()) { - localPlayerMarker = moveMarker(localPlayerMarker,newX, newY, newZ, newDimension); + localPlayerMarker = moveMarker(localPlayerMarker, newX, newY, newZ, newDimension); //TODO could be improved for translation friendliness - Snackbar.make(tileView, - activity.getString(R.string.teleported_player_to_xyz_dimension)+newX+";"+newY+";"+newZ+" ["+newDimension.name+"] ("+marker.getNamedBitmapProvider().getBitmapDisplayName()+")", + Snackbar.make(mBinding.tileView, + activity.getString(R.string.teleported_player_to_xyz_dimension) + newX + ";" + newY + ";" + newZ + " [" + newDimension.name + "] (" + marker.getNamedBitmapProvider().getBitmapDisplayName() + ")", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } else throw new Exception("Failed saving player"); - } catch (Exception e){ - Log.w(e.toString()); + } catch (Exception e) { + Log.d(this, e.toString()); - Snackbar.make(tileView, R.string.failed_teleporting_player, + Snackbar.make(mBinding.tileView, R.string.failed_teleporting_player, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } return; } case REMOVE_MARKER: { - if(marker.isCustom){ + if (marker.isCustom) { MapFragment.this.removeMarker(marker); - MarkerManager mng = MapFragment.this.worldProvider.getWorld().getMarkerManager(); + MarkerManager mng = world.getMarkerManager(); mng.removeMarker(marker, true); mng.save(); } else { //only custom markers are meant to be removable - Snackbar.make(tileView, R.string.marker_is_not_removable, + Snackbar.make(mBinding.tileView, R.string.marker_is_not_removable, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } @@ -879,49 +699,47 @@ public void onClick(DialogInterface dialog, int which) { } } }) - .setCancelable(true) - .setNegativeButton(android.R.string.cancel, null) - .show(); + .setCancelable(true) + .setNegativeButton(android.R.string.cancel, null) + .show(); } }); - //do not loop the scale tileView.setShouldLoopScale(false); //prevents flickering - this.tileView.setTransitionsEnabled(false); + tileView.setTransitionsEnabled(false); //more responsive rendering - this.tileView.setShouldRenderWhilePanning(true); - - this.tileView.setSaveEnabled(true); + tileView.setShouldRenderWhilePanning(false); + tileView.setSaveEnabled(true); - - return rootView; + return mBinding.getRoot(); } /** * Creates a new marker (looking exactly the same as the old one) on the new position, - * while removing the old marker. - * @param marker Marker to be recreated - * @param x new pos X - * @param y new pos Y - * @param z new pos Z + * while removing the old marker. + * + * @param marker Marker to be recreated + * @param x new pos X + * @param y new pos Y + * @param z new pos Z * @param dimension new pos Dimension * @return the newly created marker, which should replace the old one. */ - public AbstractMarker moveMarker(AbstractMarker marker, int x, int y, int z, Dimension dimension){ + private AbstractMarker moveMarker(AbstractMarker marker, int x, int y, int z, Dimension dimension) { AbstractMarker newMarker = marker.copy(x, y, z, dimension); - if(staticMarkers.remove(marker)) staticMarkers.add(newMarker); + if (staticMarkers.remove(marker)) staticMarkers.add(newMarker); this.removeMarker(marker); this.addMarker(newMarker); - if(marker.isCustom){ - MarkerManager mng = this.worldProvider.getWorld().getMarkerManager(); + if (marker.isCustom) { + MarkerManager mng = world.getMarkerManager(); mng.removeMarker(marker, true); mng.addMarker(newMarker, true); } @@ -929,176 +747,203 @@ public AbstractMarker moveMarker(AbstractMarker marker, int x, int y, int z, Dim return newMarker; } - private final static int MARKER_INTERVAL_CHECK = 50; - private int proceduralMarkersInterval = 0; - private volatile AsyncTask shrinkProceduralMarkersTask; - + private void doSelectionBasedEdit(@NonNull EditFunction func, @Nullable Bundle args) { + WorldActivityInterface worldActivityInterface = worldProvider.get(); + FragmentActivity activity = getActivity(); + if (worldActivityInterface == null || activity == null) return; + switch (func) { + case SNR: + case LAMPSHADE: + case CHBIOME: + case DCHUNK: + new SelectionBasedContextFreeEditTask(func, args, this, world.getWorldData().mOldBlockRegistry).execute( + new RectEditTarget( + world.getWorldData(), + mBinding.selectionBoard.getSelection(), + worldActivityInterface.getDimension()) + ); + break; + case PICER: { + PicerFragment fragment = PicerFragment.create( + world, worldActivityInterface.getDimension(), + mBinding.selectionBoard.getSelection(), null + ); + fragment.show(activity.getSupportFragmentManager(), TAG_PICER); + } + } + } /** * Calculates viewport of tileview, expressed in blocks. + * * @param marginX horizontal viewport-margin, in pixels * @param marginZ vertical viewport-margin, in pixels * @return minimum_X, maximum_X, minimum_Z, maximum_Z, dimension. (min and max are expressed in blocks!) */ - public Object[] calculateViewPort(int marginX, int marginZ){ + public Object[] calculateViewPort(int marginX, int marginZ) { - Dimension dimension = this.worldProvider.getDimension(); + Dimension dimension = this.worldProvider.get().getDimension(); // 1 chunk per tile on scale 1.0 - int pixelsPerBlockW_unscaled = MCTileProvider.TILESIZE / dimension.chunkW; - int pixelsPerBlockL_unscaled = MCTileProvider.TILESIZE / dimension.chunkL; + int pixelsPerBlockW_unscaled = MCTileProvider.TILESIZE / 16; + int pixelsPerBlockL_unscaled = MCTileProvider.TILESIZE / 16; + MapTileView tileView = mBinding.tileView; float scale = tileView.getScale(); - //scale the amount of pixels, less pixels per block if zoomed out + //scale the amount of pixels, less pixels per oldBlock if zoomed out double pixelsPerBlockW = pixelsPerBlockW_unscaled * scale; double pixelsPerBlockL = pixelsPerBlockL_unscaled * scale; - long blockX = Math.round( (tileView.getScrollX() - marginX) / pixelsPerBlockW ) - MCTileProvider.HALF_WORLDSIZE; - long blockZ = Math.round( (tileView.getScrollY() - marginZ) / pixelsPerBlockL ) - MCTileProvider.HALF_WORLDSIZE; - long blockW = Math.round( (tileView.getWidth() + marginX + marginX) / pixelsPerBlockW ); - long blockH = Math.round( (tileView.getHeight() + marginZ + marginZ) / pixelsPerBlockL ); - - return new Object[]{ blockX, blockX + blockW, blockZ, blockH, dimension }; - } - - public AsyncTask retainViewPortMarkers(final Runnable callback){ - - DisplayMetrics displayMetrics = this.getActivity().getResources().getDisplayMetrics(); - return new AsyncTask(){ - @Override - protected Void doInBackground(Object... params) { - long minX = (long) params[0], - maxX = (long) params[1], - minY = (long) params[2], - maxY = (long) params[3]; - Dimension reqDim = (Dimension) params[4]; - - for (AbstractMarker p : MapFragment.this.proceduralMarkers){ - - // do not remove static markers - if(MapFragment.this.staticMarkers.contains(p)) continue; - - if(p.x < minX || p.x > maxX || p.y < minY || p.y > maxY || p.dimension != reqDim){ - this.publishProgress(p); - } - } - return null; - } - - @Override - protected void onProgressUpdate(final AbstractMarker... values) { - for(AbstractMarker v : values) { - MapFragment.this.removeMarker(v); - } - } - - @Override - protected void onPostExecute(Void aVoid) { - callback.run(); - } + long blockX = Math.round((tileView.getScrollX() - marginX) / pixelsPerBlockW) - MCTileProvider.HALF_WORLDSIZE; + long blockZ = Math.round((tileView.getScrollY() - marginZ) / pixelsPerBlockL) - MCTileProvider.HALF_WORLDSIZE; + long blockW = Math.round((tileView.getWidth() + marginX + marginX) / pixelsPerBlockW); + long blockH = Math.round((tileView.getHeight() + marginZ + marginZ) / pixelsPerBlockL); - }.execute(this.calculateViewPort( - displayMetrics.widthPixels / 2, - displayMetrics.heightPixels / 2) - ); + return new Object[]{blockX, blockX + blockW, blockZ, blockH, dimension}; } /** * Important: this method should be run from the UI thread. + * * @param marker The marker to remove from the tile view. */ - public void removeMarker(AbstractMarker marker){ + public void removeMarker(AbstractMarker marker) { staticMarkers.remove(marker); proceduralMarkers.remove(marker); - if(marker.view != null) tileView.removeMarker(marker.view); + if (marker.view != null && mBinding.tileView != null) + mBinding.tileView.removeMarker(marker.view); } /** * Important: this method should be run from the UI thread. + * * @param marker The marker to add to the tile view. */ - public void addMarker(AbstractMarker marker){ + public synchronized void addMarker(AbstractMarker marker) { + + Activity act = getActivity(); + if (act == null) return; + + TileEntity.loadIcons(act.getAssets()); - if(proceduralMarkers.contains(marker)) return; + for (AbstractMarker abstractMarker : proceduralMarkers) { + if (abstractMarker.equals(marker)) { + removeMarker(abstractMarker); + } + } - if(shrinkProceduralMarkersTask == null - && ++proceduralMarkersInterval > MARKER_INTERVAL_CHECK){ + if (shrinkProceduralMarkersTask == null + && ++proceduralMarkersInterval > MARKER_INTERVAL_CHECK) { //shrink set of markers to viewport every so often - shrinkProceduralMarkersTask = retainViewPortMarkers(new Runnable() { - @Override - public void run() { - //reset this to start accepting viewport update requests again. - shrinkProceduralMarkersTask = null; - } - }); + + DisplayMetrics displayMetrics = act.getResources().getDisplayMetrics(); + //reset this to start accepting viewport update requests again. + shrinkProceduralMarkersTask = new RetainViewPortMarkersTask(this, () -> { + //reset this to start accepting viewport update requests again. + shrinkProceduralMarkersTask = null; + }).execute(calculateViewPort( + displayMetrics.widthPixels / 2, + displayMetrics.heightPixels / 2) + ); proceduralMarkersInterval = 0; } - proceduralMarkers.add(marker); + if (proceduralMarkers.size() > MARKERS_ON_SCREEN_TOO_MANY) { + SharedPreferences pref = act.getPreferences(Context.MODE_PRIVATE); + if (!pref.getBoolean(PREF_KEY_HAS_NOTIFIED_MARKERS_TOO_MANY, false)) { + pref.edit().putBoolean(PREF_KEY_HAS_NOTIFIED_MARKERS_TOO_MANY, true).apply(); + AlertDialog dialog = new AlertDialog.Builder(act) + .setTitle(R.string.map_smart_notice_too_many_markers) + .setMessage(R.string.map_smart_notice_too_many_markers_message) + .setPositiveButton(R.string.map_uioption_open_drawer, (dialogInterface, i) -> worldProvider.get().openDrawer()) + .setNegativeButton(R.string.general_got_it, null) + .create(); + dialog.setCanceledOnTouchOutside(false); + dialog.show(); + } + } - Activity act = getActivity(); - if (act == null) return; MarkerImageView markerView = marker.getView(act); this.filterMarker(marker); - if(tileView.getMarkerLayout().indexOfChild(markerView) >= 0){ - tileView.getMarkerLayout().removeMarker(markerView); + if (mBinding.tileView.getMarkerLayout().indexOfChild(markerView) >= 0) { + mBinding.tileView.getMarkerLayout().removeMarker(markerView); } - tileView.addMarker(markerView, + mBinding.tileView.addMarker(markerView, marker.dimension.dimensionScale * (double) marker.x / (double) MCTileProvider.HALF_WORLDSIZE, marker.dimension.dimensionScale * (double) marker.z / (double) MCTileProvider.HALF_WORLDSIZE, -0.5f, -0.5f); } - public void toggleMarkers(){ - int visibility = tileView.getMarkerLayout().getVisibility(); - tileView.getMarkerLayout().setVisibility( visibility == View.VISIBLE ? View.GONE : View.VISIBLE); + public void toggleMarkers() { + WorldActivityInterface worldProvider = this.worldProvider.get(); + if (worldProvider == null) return; + if (worldProvider.getShowMarkers()) { + resetTileView(); + } else { + for (AbstractMarker marker : proceduralMarkers) { + if (staticMarkers.contains(marker)) continue; + removeMarker(marker); + } + //resetTileView(); + } } + private String[] getLongClickOptions() { + String[] values = new String[]{ + getString(R.string.teleport_local_player), + getString(R.string.create_custom_marker), + getString(R.string.open_chunk_entity_nbt), + getString(R.string.open_chunk_tile_entity_nbt), + null + }; + values[4] = getString(mBinding.selectionBoard.hasSelection() ? + R.string.func_cancel_selection : R.string.func_begin_selection); + return values; + } - public enum LongClickOption { - - TELEPORT_LOCAL_PLAYER(R.string.teleport_local_player, null), - CREATE_MARKER(R.string.create_custom_marker, null), - //TODO TELEPORT_MULTI_PLAYER("Teleport other player", null), - ENTITY(R.string.open_chunk_entity_nbt, ChunkTag.ENTITY), - TILE_ENTITY(R.string.open_chunk_tile_entity_nbt, ChunkTag.BLOCK_ENTITY); - - public final int stringId; - public final ChunkTag dataType; + private void triggerLongPressAtCenter() { + MotionEvent event = MotionEvent.obtain(0L, 0L, 0, + (float) (mBinding.tileView.getMeasuredWidth() / 2), + (float) (mBinding.tileView.getMeasuredHeight() / 2), 0); + onLongPressed(event); + // ... + } - LongClickOption(int id, ChunkTag dataType){ - this.stringId = id; - this.dataType = dataType; - } + /** + * Map long press handler, shows a list of options. + * + * @param event long press event. + */ + private void onLongPressed(@NonNull MotionEvent event) { + Dimension dimension = worldProvider.get().getDimension(); - } + // 1 chunk per tile on scale 1.0 + int pixelsPerBlockW_unscaled = MCTileProvider.TILESIZE / dimension.chunkW; + int pixelsPerBlockL_unscaled = MCTileProvider.TILESIZE / dimension.chunkL; - public String[] getLongClickOptions(){ - LongClickOption[] values = LongClickOption.values(); - int len = values.length; - String[] options = new String[len]; - for(int i = 0; i < len; i++){ - options[i] = getString(values[i].stringId); - } - return options; - } + float scale = mBinding.tileView.getScale(); + float pixelsPerBlockScaledW = pixelsPerBlockW_unscaled * scale; + float pixelsPerBlockScaledL = pixelsPerBlockL_unscaled * scale; - public void onLongClick(final double worldX, final double worldZ){ + double worldX = (((mBinding.tileView.getScrollX() + event.getX()) / pixelsPerBlockScaledW) - MCTileProvider.HALF_WORLDSIZE) / dimension.dimensionScale; + double worldZ = (((mBinding.tileView.getScrollY() + event.getY()) / pixelsPerBlockScaledL) - MCTileProvider.HALF_WORLDSIZE) / dimension.dimensionScale; + //MapFragment.this.onLongClick(worldX, worldZ); - final Activity activity = MapFragment.this.getActivity(); + final Activity activity = getActivity(); + if (activity == null) return; - final Dimension dim = this.worldProvider.getDimension(); + final Dimension dim = this.worldProvider.get().getDimension(); double chunkX = worldX / dim.chunkW; double chunkZ = worldZ / dim.chunkL; @@ -1108,245 +953,276 @@ public void onLongClick(final double worldX, final double worldZ){ final int chunkZint = chunkZ < 0 ? (((int) chunkZ) - 1) : ((int) chunkZ); - final View container = activity.findViewById(R.id.world_content); - if(container == null){ - Log.w("CANNOT FIND MAIN CONTAINER, WTF"); + if (container == null) { + Log.d(this, "CANNOT FIND MAIN CONTAINER, WTF"); return; } - new AlertDialog.Builder(activity) - .setTitle(getString(R.string.postion_2D_floats_with_chunkpos, worldX, worldZ, chunkXint, chunkZint, dim.name)) - .setItems(getLongClickOptions(), new DialogInterface.OnClickListener() { - @SuppressLint("SetTextI18n") - public void onClick(DialogInterface dialog, int which) { - - final LongClickOption chosen = LongClickOption.values()[which]; - + AlertDialog alertDialog = new AlertDialog.Builder(new ContextThemeWrapper(activity, R.style.AppTheme_Floating)) + .setTitle(getString(R.string.postion_2D_floats_with_chunkpos, worldX, worldZ, chunkXint, chunkZint)) + .setItems(getLongClickOptions(), (dialog, which) -> { + + + switch (which) { + case 0: + onChooseTeleportPlayer((float) worldX, (float) worldZ, dim, container); + break; + case 1: + onChooseAddMarker((int) worldX, (int) worldZ, activity, dim, container); + break; + case 2: + onChooseEditEntitiesOrTileEntities(dim, chunkXint, chunkZint, container, true); + break; + case 3: + onChooseEditEntitiesOrTileEntities(dim, chunkXint, chunkZint, container, false); + break; + case 4: + beginOrEndSelection((int) worldX, (int) worldZ); + } - switch (chosen){ - case TELEPORT_LOCAL_PLAYER:{ - try { - final EditableNBT playerEditable = MapFragment.this.worldProvider.getEditablePlayer(); - if(playerEditable == null) throw new Exception("Player is null"); - - Iterator playerIter = playerEditable.getTags().iterator(); - if(!playerIter.hasNext()) throw new Exception("Player DB entry is empty!"); - - //db entry consists of one compound tag - final CompoundTag playerTag = (CompoundTag) playerIter.next(); - - ListTag posVec = (ListTag) playerTag.getChildTagByKey("Pos"); - - if (posVec == null) throw new Exception("No \"Pos\" specified"); - - final List playerPos = posVec.getValue(); - if(playerPos == null) - throw new Exception("No \"Pos\" specified"); - if (playerPos.size() != 3) - throw new Exception("\"Pos\" value is invalid. value: " + posVec.getValue().toString()); - - final IntTag dimensionId = (IntTag) playerTag.getChildTagByKey("DimensionId"); - if(dimensionId == null || dimensionId.getValue() == null) - throw new Exception("No \"DimensionId\" specified"); - - - float playerY = (float) playerPos.get(1).getValue(); - - - View yForm = LayoutInflater.from(activity).inflate(R.layout.y_coord_form, null); - final EditText yInput = (EditText) yForm.findViewById(R.id.y_input); - yInput.setText(String.valueOf(playerY)); - - final float newX = (float) worldX; - final float newZ = (float) worldZ; - - new AlertDialog.Builder(activity) - .setTitle(chosen.stringId) - .setView(yForm) - .setPositiveButton(R.string.action_teleport, new DialogInterface.OnClickListener() { - @SuppressWarnings("RedundantCast") - @Override - public void onClick(DialogInterface dialog, int which) { - - float newY; - Editable value = yInput.getText(); - if(value == null) newY = 64f; - else { - try { - newY = (float) Float.parseFloat(value.toString());//removes excessive precision - } catch (Exception e){ - newY = 64f; - } - } - - ((FloatTag) playerPos.get(0)).setValue(newX); - ((FloatTag) playerPos.get(1)).setValue(newY); - ((FloatTag) playerPos.get(2)).setValue(newZ); - dimensionId.setValue(dim.id); - - if(playerEditable.save()){ - - MapFragment.this.localPlayerMarker = MapFragment.this.moveMarker( - MapFragment.this.localPlayerMarker, - (int) newX, (int) newY, (int) newZ, dim); - - Snackbar.make(container, - String.format(getString(R.string.teleported_player_to_xyz_dim), newX, newY, newZ, dim.name), - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } else { - Snackbar.make(container, - R.string.failed_teleporting_player, - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - } - }) - .setCancelable(true) - .setNegativeButton(android.R.string.cancel, null) - .show(); - return; - - } catch (Exception e){ - e.printStackTrace(); - Snackbar.make(container, R.string.failed_to_find_or_edit_local_player_data, - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - return; - } - } - case CREATE_MARKER:{ + }) + .setCancelable(true) + .setNegativeButton(android.R.string.cancel, null) + .show(); + alertDialog.getListView().post(() -> + alertDialog.getListView().smoothScrollToPositionFromTop(4, 40)); + Window window = alertDialog.getWindow(); + if (window != null) { + window.setBackgroundDrawable(getResources().getDrawable(R.drawable.bg_dialog_transparent)); + window.setDimAmount(0.3f); + } - View createMarkerForm = LayoutInflater.from(activity).inflate(R.layout.create_marker_form, null); + } - final EditText markerNameInput = (EditText) createMarkerForm.findViewById(R.id.marker_displayname_input); - markerNameInput.setText(R.string.default_custom_marker_name); - final EditText markerIconNameInput = (EditText) createMarkerForm.findViewById(R.id.marker_iconname_input); - markerIconNameInput.setText("blue_marker"); - final EditText xInput = (EditText) createMarkerForm.findViewById(R.id.x_input); - xInput.setText(String.valueOf((int) worldX)); - final EditText yInput = (EditText) createMarkerForm.findViewById(R.id.y_input); - yInput.setText(String.valueOf(64)); - final EditText zInput = (EditText) createMarkerForm.findViewById(R.id.z_input); - zInput.setText(String.valueOf((int) worldZ)); + private void beginOrEndSelection(int worldX, int worldZ) { + if (mBinding.selectionBoard.hasSelection()) { + mBinding.selectionBoard.endSelection(); + // If it's already replaced don't kill the wrong pig. + if (mFloatingFragment instanceof SelectionMenuFragment) closeFloatPane(); + } else { + mBinding.selectionBoard.beginSelection(worldX, worldZ); + SelectionMenuFragment fragment = SelectionMenuFragment + .newInstance(mBinding.selectionBoard.getSelection(), world.getWorldData().mOldBlockRegistry, this::doSelectionBasedEdit); + openFloatPane(fragment); + setUpSelectionMenu(); + Activity activity = getActivity(); + if (activity != null) { + Log.logFirebaseEvent(activity, Log.CustomFirebaseEvent.SELECTION); + activity.getPreferences(Context.MODE_PRIVATE).edit() + .putBoolean(PREF_KEY_HAS_USED_SELECTION, true).apply(); + } + } + } + private void onChooseEditEntitiesOrTileEntities(Dimension dim, int chunkXint, int chunkZint, View container, boolean isEntity) { + final Chunk chunk; + try { + chunk = world.getWorldData() + .getChunk(chunkXint, chunkZint, dim); + } catch (Exception e) { + Log.d(this, e); + Toast.makeText(getContext(), R.string.error_could_not_open_world, Toast.LENGTH_SHORT).show(); + return; + } - new AlertDialog.Builder(activity) - .setTitle(chosen.stringId) - .setView(createMarkerForm) - .setPositiveButton("Create marker", new DialogInterface.OnClickListener() { + if (!chunkDataNBT(chunk, isEntity)) { + Snackbar.make(container, String.format(getString(R.string.failed_to_load_x), + getString(isEntity ? + R.string.open_chunk_entity_nbt : R.string.open_chunk_tile_entity_nbt)), + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + } - public void failParseSnackbarReport(int msg){ - Snackbar.make(container, msg, - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - - @Override - public void onClick(DialogInterface dialog, int which) { - - try { - String displayName = markerNameInput.getText().toString(); - if (displayName.equals("") || displayName.contains("\"")) { - failParseSnackbarReport(R.string.marker_invalid_name); - return; - } - String iconName = markerIconNameInput.getText().toString(); - if (iconName.equals("") || iconName.contains("\"")) { - failParseSnackbarReport(R.string.invalid_icon_name); - return; - } - - int xM, yM, zM; - - String xStr = xInput.getText().toString(); - try { - xM = Integer.parseInt(xStr); - } catch (NumberFormatException e) { - failParseSnackbarReport(R.string.invalid_x_coordinate); - return; - } - String yStr = yInput.getText().toString(); - try { - yM = Integer.parseInt(yStr); - } catch (NumberFormatException e) { - failParseSnackbarReport(R.string.invalid_y_coordinate); - return; - } - - String zStr = zInput.getText().toString(); - try { - zM = Integer.parseInt(zStr); - } catch (NumberFormatException e) { - failParseSnackbarReport(R.string.invalid_z_coordinate); - return; - } - - AbstractMarker marker = MarkerManager.markerFromData(displayName, iconName, xM, yM, zM, dim); - MarkerManager mng = MapFragment.this.worldProvider.getWorld().getMarkerManager(); - mng.addMarker(marker, true); - - MapFragment.this.addMarker(marker); - - mng.save(); - - } catch (Exception e){ - e.printStackTrace(); - failParseSnackbarReport(R.string.failed_to_create_marker); - } - } - }) - .setCancelable(true) - .setNegativeButton(android.R.string.cancel, null) - .show(); + private void onChooseAddMarker(int worldX, int worldZ, Activity activity, Dimension dim, View container) { + View createMarkerForm = LayoutInflater.from(activity).inflate(R.layout.create_marker_form, null); + final EditText markerNameInput = createMarkerForm.findViewById(R.id.marker_displayname_input); + markerNameInput.setText(R.string.default_custom_marker_name); + final EditText markerIconNameInput = createMarkerForm.findViewById(R.id.marker_iconname_input); + markerIconNameInput.setText("blue_marker"); + final EditText xInput = createMarkerForm.findViewById(R.id.x_input); + xInput.setText(String.valueOf(worldX)); + final EditText yInput = createMarkerForm.findViewById(R.id.y_input); + yInput.setText(String.valueOf(64)); + final EditText zInput = createMarkerForm.findViewById(R.id.z_input); + zInput.setText(String.valueOf(worldZ)); + new AlertDialog.Builder(activity) + .setTitle(R.string.create_custom_marker) + .setView(createMarkerForm) + .setPositiveButton("Create marker", new DialogInterface.OnClickListener() { + + void failParseSnackbarReport(int msg) { + Snackbar.make(container, msg, + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + @Override + public void onClick(DialogInterface dialog, int which) { + try { + String displayName = markerNameInput.getText().toString(); + if (displayName.equals("") || displayName.contains("\"")) { + failParseSnackbarReport(R.string.marker_invalid_name); + return; + } + String iconName = markerIconNameInput.getText().toString(); + if (iconName.equals("") || iconName.contains("\"")) { + failParseSnackbarReport(R.string.invalid_icon_name); return; } - /* TODO multi player teleporting - case TELEPORT_MULTI_PLAYER:{ - - break; - }*/ - case ENTITY: - case TILE_ENTITY:{ - final World world = MapFragment.this.worldProvider.getWorld(); - final ChunkManager chunkManager = new ChunkManager(world.getWorldData(), dim); - final Chunk chunk = chunkManager.getChunk(chunkXint, chunkZint); - - if(!chunkDataNBT(chunk, chosen == LongClickOption.ENTITY)){ - Snackbar.make(container, String.format(getString(R.string.failed_to_load_x), getString(chosen.stringId)), - Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } + int xM, yM, zM; + String xStr = xInput.getText().toString(); + try { + xM = Integer.parseInt(xStr); + } catch (NumberFormatException e) { + failParseSnackbarReport(R.string.invalid_x_coordinate); + return; + } + String yStr = yInput.getText().toString(); + try { + yM = Integer.parseInt(yStr); + } catch (NumberFormatException e) { + failParseSnackbarReport(R.string.invalid_y_coordinate); + return; + } + String zStr = zInput.getText().toString(); + try { + zM = Integer.parseInt(zStr); + } catch (NumberFormatException e) { + failParseSnackbarReport(R.string.invalid_z_coordinate); + return; } - } + AbstractMarker marker = MarkerManager.markerFromData(displayName, iconName, xM, yM, zM, dim); + MarkerManager mng = world.getMarkerManager(); + mng.addMarker(marker, true); + + MapFragment.this.addMarker(marker); + + mng.save(); + } catch (Exception e) { + e.printStackTrace(); + failParseSnackbarReport(R.string.failed_to_create_marker); + } } }) .setCancelable(true) .setNegativeButton(android.R.string.cancel, null) .show(); + + return; + } + + private void onChooseTeleportPlayer(float worldX, float worldZ, Dimension dim, View container) { + try { + Activity activity = getActivity(); + assert activity != null; + + final EditableNBT playerEditable = worldProvider.get().getEditablePlayer(); + if (playerEditable == null) + throw new Exception("Player is null"); + + Iterator playerIter = playerEditable.getTags().iterator(); + if (!playerIter.hasNext()) + throw new Exception("Player DB entry is empty!"); + + //db entry consists of one compound tag + final CompoundTag playerTag = (CompoundTag) playerIter.next(); + + ListTag posVec = (ListTag) playerTag.getChildTagByKey("Pos"); + + if (posVec == null) throw new Exception("No \"Pos\" specified"); + + final List playerPos = posVec.getValue(); + if (playerPos == null) + throw new Exception("No \"Pos\" specified"); + if (playerPos.size() != 3) + throw new Exception("\"Pos\" value is invalid. value: " + posVec.getValue().toString()); + + final IntTag dimensionId = (IntTag) playerTag.getChildTagByKey("DimensionId"); + if (dimensionId == null || dimensionId.getValue() == null) + throw new Exception("No \"DimensionId\" specified"); + + + float playerY = (float) playerPos.get(1).getValue(); + + + View yForm = LayoutInflater.from(activity).inflate(R.layout.y_coord_form, null); + final EditText yInput = yForm.findViewById(R.id.y_input); + yInput.setText(String.valueOf(playerY)); + + final float newX = worldX; + final float newZ = worldZ; + + new AlertDialog.Builder(activity) + .setTitle(R.string.teleport_local_player) + .setView(yForm) + .setPositiveButton(R.string.action_teleport, (dialog1, which1) -> { + + float newY; + Editable value = yInput.getText(); + if (value == null) newY = 64f; + else { + try { + newY = Float.parseFloat(value.toString());//removes excessive precision + } catch (Exception e) { + newY = 64f; + } + } + + ((FloatTag) playerPos.get(0)).setValue(newX); + ((FloatTag) playerPos.get(1)).setValue(newY); + ((FloatTag) playerPos.get(2)).setValue(newZ); + dimensionId.setValue(dim.id); + + if (playerEditable.save()) { + + MapFragment.this.localPlayerMarker = MapFragment.this.moveMarker( + MapFragment.this.localPlayerMarker, + (int) newX, (int) newY, (int) newZ, dim); + + Snackbar.make(container, + getString(R.string.teleported_player_to_xyz_dim, newX, newY, newZ), + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } else { + Snackbar.make(container, + R.string.failed_teleporting_player, + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + }) + .setCancelable(true) + .setNegativeButton(android.R.string.cancel, null) + .show(); + + } catch (Exception e) { + e.printStackTrace(); + Snackbar.make(container, R.string.failed_to_find_or_edit_local_player_data, + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } } /** * Opens the chunk data nbt editor. * - * @param chunk the chunk to edit - * @param entity if it is entity data (True) or block-entity data (False) + * @param chunk the chunk to edit + * @param entity if it is entity data (True) or oldBlock-entity data (False) * @return false when the chunk data could not be loaded. */ - private boolean chunkDataNBT(Chunk chunk, boolean entity){ + private boolean chunkDataNBT(Chunk chunk, boolean entity) { NBTChunkData chunkData; try { chunkData = entity ? chunk.getEntity() : chunk.getBlockEntity(); @@ -1356,38 +1232,223 @@ private boolean chunkDataNBT(Chunk chunk, boolean entity){ } //just open the editor if the data is there for us to edit it - this.worldProvider.openChunkNBTEditor(chunk.x, chunk.z, chunkData, this.tileView); + this.worldProvider.get().openChunkNBTEditor(chunk.mChunkX, chunk.mChunkZ, chunkData, mBinding.tileView); return true; } - @Override public void onDestroy() { super.onDestroy(); + if (mBinding != null) { + mBinding.tileView.destroy(); + } + // TODO: should we...👇 + //mBinding.tileView = null; + minecraftTileProvider = null; + } + public void openMarkerFilter() { + + final Activity activity = this.getActivity(); - tileView.destroy(); - tileView = null; - minecraftTileProvider = null; + final List choices = new ArrayList<>(markerFilter.values()); + + //sort on names, nice for the user. + Collections.sort(choices, (a, b) -> a.namedBitmap.getNamedBitmapProvider().getBitmapDisplayName().compareTo(b.namedBitmap.getNamedBitmapProvider().getBitmapDisplayName())); + + + new AlertDialog.Builder(activity) + .setTitle(R.string.filter_markers) + .setAdapter(new BitmapChoiceListAdapter(activity, choices), null) + .setCancelable(true) + .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> { + //save all the temporary states. + for (BitmapChoiceListAdapter.NamedBitmapChoice choice : choices) { + choice.enabled = choice.enabledTemp; + } + MapFragment.this.updateMarkerFilter(); + }) + .setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> { + //reset all the temporary states. + for (BitmapChoiceListAdapter.NamedBitmapChoice choice : choices) { + choice.enabledTemp = choice.enabled; + } + }) + .setOnCancelListener(dialogInterface -> { + //reset all the temporary states. + for (BitmapChoiceListAdapter.NamedBitmapChoice choice : choices) { + choice.enabledTemp = choice.enabled; + } + }) + .show(); } - public static class BitmapChoiceListAdapter extends ArrayAdapter { + public void updateMarkerFilter() { + for (AbstractMarker marker : this.proceduralMarkers) { + filterMarker(marker); + } + } - public static class NamedBitmapChoice { + public void filterMarker(AbstractMarker marker) { + WorldActivityInterface worldProvider = this.worldProvider.get(); + BitmapChoiceListAdapter.NamedBitmapChoice choice = markerFilter.get(marker.getNamedBitmapProvider()); + if (choice != null) { + marker.getView(this.getActivity()).setVisibility( + (choice.enabled && marker.dimension == worldProvider.getDimension()) + ? View.VISIBLE : View.INVISIBLE); + } else { + marker.getView(this.getActivity()) + .setVisibility(marker.dimension == worldProvider.getDimension() + ? View.VISIBLE : View.INVISIBLE); + } + } - //Using a handle to facilitate bitmap swapping without breaking the filter. - final NamedBitmapProviderHandle namedBitmap; - boolean enabledTemp; - boolean enabled; + public void refreshAfterEdit() { + mBinding.tileView.getTileCanvasViewGroup().clear(); + mBinding.tileView.getTileCanvasViewGroup().requiredBeginRenderTask(); + } + + public void resetTileView() { + if (mBinding.tileView != null) { + WorldActivityInterface worldProvider = this.worldProvider.get(); + + updateMarkerFilter(); + + mBinding.tileView.getDetailLevelManager().setLevelType(worldProvider.getMapType()); + + invalidateTileView(); + } + } + + public void invalidateTileView() { + WorldActivityInterface worldProvider = this.worldProvider.get(); + MapType redo = worldProvider.getMapType(); + DetailLevelManager manager = mBinding.tileView.getDetailLevelManager(); + //just swap mapType twice; it is not rendered, but it invalidates all tiles. + manager.setLevelType(MapType.CHESS); + manager.setLevelType(redo); + //all tiles will now reload as soon as the tileView is drawn (user scrolls -> redraw) + } + + /** + * This is a convenience method to scrollToAndCenter after layout (which won't happen if called directly in onCreate + * see https://github.com/moagrius/TileView/wiki/FAQ + */ + public void frameTo(final double worldX, final double worldZ) { + mBinding.tileView.post(() -> { + Dimension dimension = worldProvider.get().getDimension(); + if (mBinding.tileView != null) mBinding.tileView.scrollToAndCenter( + dimension.dimensionScale * worldX / (double) MCTileProvider.HALF_WORLDSIZE, + dimension.dimensionScale * worldZ / (double) MCTileProvider.HALF_WORLDSIZE); + }); + } + + public enum MarkerTapOption { + + TELEPORT_LOCAL_PLAYER(R.string.teleport_local_player), + REMOVE_MARKER(R.string.remove_custom_marker); + + public final int stringId; + + MarkerTapOption(int id) { + this.stringId = id; + } + + } + + public enum LongClickOption { + + TELEPORT_LOCAL_PLAYER(R.string.teleport_local_player, null), + CREATE_MARKER(R.string.create_custom_marker, null), + //TODO TELEPORT_MULTI_PLAYER("Teleport other player", null), + ENTITY(R.string.open_chunk_entity_nbt, ChunkTag.ENTITY), + TILE_ENTITY(R.string.open_chunk_tile_entity_nbt, ChunkTag.BLOCK_ENTITY), + BEGIN_SELECTION(R.string.func_begin_selection, null); + + public final int stringId; + public final ChunkTag dataType; + + LongClickOption(int id, ChunkTag dataType) { + this.stringId = id; + this.dataType = dataType; + } + + } + +// private class MapTileView extends TileView{@Override +// public void onLongPress(MotionEvent event) { +// +// Dimension dimension = worldProvider.get().getDimension(); +// +// // 1 chunk per tile on scale 1.0 +// int pixelsPerBlockW_unscaled = MCTileProvider.TILESIZE / dimension.chunkW; +// int pixelsPerBlockL_unscaled = MCTileProvider.TILESIZE / dimension.chunkL; +// +// float pixelsPerBlockScaledW = pixelsPerBlockW_unscaled * this.getScale(); +// float pixelsPerBlockScaledL = pixelsPerBlockL_unscaled * this.getScale(); +// +// +// double worldX = (((this.getScrollX() + event.getX()) / pixelsPerBlockScaledW) - MCTileProvider.HALF_WORLDSIZE) / dimension.dimensionScale; +// double worldZ = (((this.getScrollY() + event.getY()) / pixelsPerBlockScaledL) - MCTileProvider.HALF_WORLDSIZE) / dimension.dimensionScale; +// +// MapFragment.this.onLongClick(worldX, worldZ); +// }} + + public static class MarkerListAdapter extends ArrayAdapter { + + + MarkerListAdapter(Context context, List objects) { + super(context, 0, objects); + } + + @NonNull + @Override + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + + RelativeLayout v = (RelativeLayout) convertView; + + if (v == null) { + LayoutInflater vi; + vi = LayoutInflater.from(getContext()); + v = (RelativeLayout) vi.inflate(R.layout.marker_list_entry, parent, false); + } + + AbstractMarker m = getItem(position); + + if (m != null) { + TextView name = v.findViewById(R.id.marker_name); + TextView xz = v.findViewById(R.id.marker_xz); + ImageView icon = v.findViewById(R.id.marker_icon); + + name.setText(m.getNamedBitmapProvider().getBitmapDisplayName()); + String xzStr = String.format(Locale.ENGLISH, "x: %d, y: %d, z: %d", m.x, m.y, m.z); + xz.setText(xzStr); + + m.loadIcon(icon); - public NamedBitmapChoice(NamedBitmapProviderHandle namedBitmap, boolean enabled){ - this.namedBitmap = namedBitmap; - this.enabled = this.enabledTemp = enabled; } + + return v; } - public BitmapChoiceListAdapter(Context context, List objects) { + } + + public static class BitmapChoiceListAdapter extends ArrayAdapter { + + private CompoundButton.OnCheckedChangeListener changeListener = new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean b) { + Object tag = compoundButton.getTag(); + if (tag == null) return; + int position = (int) tag; + final NamedBitmapChoice m = getItem(position); + if (m == null) return; + m.enabledTemp = b; + } + }; + + BitmapChoiceListAdapter(Context context, List objects) { super(context, 0, objects); } @@ -1396,16 +1457,16 @@ public BitmapChoiceListAdapter(Context context, List objects) public View getView(final int position, View v, @NonNull ViewGroup parent) { final NamedBitmapChoice m = getItem(position); - if(m == null) return new RelativeLayout(getContext()); + if (m == null) return new RelativeLayout(getContext()); if (v == null) v = LayoutInflater - .from(getContext()) - .inflate(R.layout.img_name_check_list_entry, parent, false); + .from(getContext()) + .inflate(R.layout.img_name_check_list_entry, parent, false); - ImageView img = (ImageView) v.findViewById(R.id.entry_img); - TextView text = (TextView) v.findViewById(R.id.entry_text); - final CheckBox check = (CheckBox) v.findViewById(R.id.entry_check); + ImageView img = v.findViewById(R.id.entry_img); + TextView text = v.findViewById(R.id.entry_text); + final CheckBox check = v.findViewById(R.id.entry_check); img.setImageBitmap(m.namedBitmap.getNamedBitmapProvider().getBitmap()); text.setText(m.namedBitmap.getNamedBitmapProvider().getBitmapDisplayName()); @@ -1416,150 +1477,159 @@ public View getView(final int position, View v, @NonNull ViewGroup parent) { return v; } - private CompoundButton.OnCheckedChangeListener changeListener = new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean b) { - Object tag = compoundButton.getTag(); - if(tag == null) return; - int position = (int) tag; - final NamedBitmapChoice m = getItem(position); - if(m == null) return; - m.enabledTemp = b; + static class NamedBitmapChoice { + + //Using a handle to facilitate bitmap swapping without breaking the filter. + final NamedBitmapProviderHandle namedBitmap; + boolean enabledTemp; + boolean enabled; + + NamedBitmapChoice(NamedBitmapProviderHandle namedBitmap, boolean enabled) { + this.namedBitmap = namedBitmap; + this.enabled = this.enabledTemp = enabled; } - }; + } } + private static class GetPlayerTask extends AsyncTask { - //static, remember choice while app is open. - static Map markerFilter = new HashMap<>(); + private final WeakReference owner; + private final WeakReference view; + private final WeakReference activity; - static { - //entities are enabled by default - for (Entity v : Entity.values()) { - //skip things without a bitmap (dropped items etc.) - //skip entities with placeholder ids (900+) - if(v.sheetPos < 0 || v.id >= 900) continue; - markerFilter.put(v.getNamedBitmapProvider(), - new BitmapChoiceListAdapter.NamedBitmapChoice(v, true)); + private GetPlayerTask(MapFragment owner, View view, Activity activity) { + this.owner = new WeakReference<>(owner); + this.view = new WeakReference<>(view); + this.activity = new WeakReference<>(activity); } - //tile-entities are disabled by default - for (TileEntity v : TileEntity.values()) { - markerFilter.put(v.getNamedBitmapProvider(), - new BitmapChoiceListAdapter.NamedBitmapChoice(v, false)); + + @Override + protected String[] doInBackground(Void... arg0) { + try { + return owner.get().world.getWorldData().getNetworkPlayerNames(); + } catch (Exception e) { + return null; + } } - } + protected void onPostExecute(final String[] players) { + owner.get().getActivity().runOnUiThread(() -> { - public void openMarkerFilter() { + if (players == null) { + Snackbar.make(view.get(), R.string.failed_to_retrieve_player_data, Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + return; + } - final Activity activity = this.getActivity(); + if (players.length == 0) { + Snackbar.make(view.get(), R.string.no_multiplayer_data_found, Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + return; + } - final List choices = new ArrayList<>(); - choices.addAll(markerFilter.values()); + //NBT tag type spinner + final Spinner spinner = new Spinner(activity.get()); + ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>(activity.get(), + android.R.layout.simple_spinner_item, players); - //sort on names, nice for the user. - Collections.sort(choices, new Comparator() { - @Override - public int compare(BitmapChoiceListAdapter.NamedBitmapChoice a, BitmapChoiceListAdapter.NamedBitmapChoice b) { - return a.namedBitmap.getNamedBitmapProvider().getBitmapDisplayName().compareTo(b.namedBitmap.getNamedBitmapProvider().getBitmapDisplayName()); - } - }); + spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(spinnerArrayAdapter); + //wrap layout in alert + new AlertDialog.Builder(activity.get()) + .setTitle(R.string.go_to_player) + .setView(spinner) + .setPositiveButton(R.string.go_loud, new DialogInterface.OnClickListener() { - new AlertDialog.Builder(activity) - .setTitle(R.string.filter_markers) - .setAdapter(new BitmapChoiceListAdapter(activity, choices), null) - .setCancelable(true) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - //save all the temporary states. - for(BitmapChoiceListAdapter.NamedBitmapChoice choice : choices){ - choice.enabled = choice.enabledTemp; - } - MapFragment.this.updateMarkerFilter(); - } - }) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - //reset all the temporary states. - for(BitmapChoiceListAdapter.NamedBitmapChoice choice : choices){ - choice.enabledTemp = choice.enabled; - } - } - }) - .setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialogInterface) { - //reset all the temporary states. - for(BitmapChoiceListAdapter.NamedBitmapChoice choice : choices){ - choice.enabledTemp = choice.enabled; - } - } - }) - .show(); - } + public void onClick(DialogInterface dialog, int whichButton) { - public void updateMarkerFilter(){ - for(AbstractMarker marker : this.proceduralMarkers){ - filterMarker(marker); - } - } + //new tag type + int spinnerIndex = spinner.getSelectedItemPosition(); + String playerKey = players[spinnerIndex]; - public void filterMarker(AbstractMarker marker){ - BitmapChoiceListAdapter.NamedBitmapChoice choice = markerFilter.get(marker.getNamedBitmapProvider()); - if(choice != null){ - marker.getView(this.getActivity()).setVisibility( - (choice.enabled && marker.dimension == worldProvider.getDimension()) - ? View.VISIBLE : View.INVISIBLE); - } else { - marker.getView(this.getActivity()) - .setVisibility(marker.dimension == worldProvider.getDimension() - ? View.VISIBLE : View.INVISIBLE); - } - } + try { + DimensionVector3 playerPos = owner.get().world.getMultiPlayerPos(playerKey); + + Snackbar.make(owner.get().mBinding.tileView, + owner.get().getString(R.string.something_at_xyz_dim_float, + playerKey, + playerPos.x, + playerPos.y, + playerPos.z), + Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); - public void resetTileView(){ - if(this.tileView != null){ - worldProvider.logFirebaseEvent(WorldActivity.CustomFirebaseEvent.MAPFRAGMENT_RESET); + WorldActivityInterface worldProvider = owner.get().worldProvider.get(); + Log.logFirebaseEvent(activity.get(), Log.CustomFirebaseEvent.GPS_LOCATE); - updateMarkerFilter(); + if (playerPos.dimension != worldProvider.getDimension()) { + worldProvider.changeMapType(playerPos.dimension.defaultMapType, playerPos.dimension); + } - tileView.getDetailLevelManager().setLevelType(worldProvider.getMapType()); + owner.get().frameTo((double) playerPos.x, (double) playerPos.z); - invalidateTileView(); + } catch (Exception e) { + Snackbar.make(view.get(), e.getMessage(), Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + + } + }) + //or alert is cancelled + .setNegativeButton(android.R.string.cancel, null) + .show(); + }); } - } - public void invalidateTileView(){ - MapType redo = worldProvider.getMapType(); - DetailLevelManager manager = tileView.getDetailLevelManager(); - //just swap mapType twice; it is not rendered, but it invalidates all tiles. - manager.setLevelType(MapType.CHESS); - manager.setLevelType(redo); - //all tiles will now reload as soon as the tileView is drawn (user scrolls -> redraw) } + private static class RetainViewPortMarkersTask extends AsyncTask { + private final WeakReference owner; + private final Runnable callback; - /** - * This is a convenience method to scrollToAndCenter after layout (which won't happen if called directly in onCreate - * see https://github.com/moagrius/TileView/wiki/FAQ - */ - public void frameTo( final double worldX, final double worldZ ) { - this.tileView.post(new Runnable() { - @Override - public void run() { - Dimension dimension = worldProvider.getDimension(); - if(tileView != null) tileView.scrollToAndCenter( - dimension.dimensionScale * worldX / (double) MCTileProvider.HALF_WORLDSIZE, - dimension.dimensionScale * worldZ / (double) MCTileProvider.HALF_WORLDSIZE); + private RetainViewPortMarkersTask(MapFragment owner, Runnable callback) { + this.owner = new WeakReference<>(owner); + this.callback = callback; + } + + @Override + protected Void doInBackground(Object... params) { + long minX = (long) params[0], + maxX = (long) params[1], + minY = (long) params[2], + maxY = (long) params[3]; + Dimension reqDim = (Dimension) params[4]; + + CopyOnWriteArraySet proceduralMarkers = owner.get().proceduralMarkers; + + for (AbstractMarker p : proceduralMarkers) { + + // do not remove static markers + if (owner.get().staticMarkers.contains(p)) continue; + + if (p.x < minX || p.x > maxX || p.y < minY || p.y > maxY || p.dimension != reqDim) { + this.publishProgress(p); + } } - }); + return null; + } + + @Override + protected void onProgressUpdate(final AbstractMarker... values) { + for (AbstractMarker v : values) { + owner.get().removeMarker(v); + } + } + + @Override + protected void onPostExecute(Void aVoid) { + callback.run(); + } + } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/MapTileView.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/MapTileView.java new file mode 100644 index 00000000..eb4cd759 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/MapTileView.java @@ -0,0 +1,109 @@ +package com.mithrilmania.blocktopograph.map; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; + +import com.mithrilmania.blocktopograph.map.selection.SelectionView; +import com.qozix.tileview.TileView; + +import java.lang.ref.WeakReference; + +/** + * A wrapper of TileView in order to handle some of its events. + */ +public class MapTileView extends TileView { + + /** + * Long press callback. + */ + private OnLongPressListener mOnLongPressListener; + private WeakReference mSelectionView; + private GestureDetector.OnDoubleTapListener mOuterDoubleTapListener; + + private boolean mTouchable = true; + + public MapTileView(Context context) { + super(context); + } + + public MapTileView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public MapTileView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public void onLongPress(MotionEvent event) { + if (mOnLongPressListener != null) mOnLongPressListener.onLongPressed(event); + } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + updateSelection(); + } + + @Override + public boolean onDoubleTap(MotionEvent event) { + if (mOuterDoubleTapListener != null) mOuterDoubleTapListener.onDoubleTap(event); + return true; + } + + public void setOuterDoubleTapListener(GestureDetector.OnDoubleTapListener outerDoubleTapListener) { + mOuterDoubleTapListener = outerDoubleTapListener; + } + + public void updateSelection() { + SelectionView selectionView; + if (mSelectionView != null && (selectionView = mSelectionView.get()) != null + && selectionView.hasSelection()) { + //selectionView.invalidate(); + selectionView.requestLayout(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (mTouchable) + return super.onTouchEvent(event); + return false; + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent event) { + if (super.onSingleTapConfirmed(event)) return true; + if (mOnLongPressListener != null) { + mOnLongPressListener.onLongPressed(event); + return true; + } + return false; + } + + /** + * Sets the long press callback. + * + * @param mOnLongPressListener long press callback. + */ + public void setOnLongPressListener(OnLongPressListener mOnLongPressListener) { + this.mOnLongPressListener = mOnLongPressListener; + } + + public void setSelectionView(SelectionView selectionView) { + mSelectionView = new WeakReference<>(selectionView); + } + + public void setTouchable(boolean touchable) { + mTouchable = touchable; + } + + /** + * Interface for long press callback. + */ + public interface OnLongPressListener { + void onLongPressed(MotionEvent event); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerAsyncTask.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerAsyncTask.java index eed95f97..48e0154c 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerAsyncTask.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerAsyncTask.java @@ -1,10 +1,13 @@ package com.mithrilmania.blocktopograph.map; import android.os.AsyncTask; -import com.mithrilmania.blocktopograph.Log; +import android.view.ViewGroup; +import android.view.ViewParent; +import com.mithrilmania.blocktopograph.Log; import com.mithrilmania.blocktopograph.WorldActivityInterface; -import com.mithrilmania.blocktopograph.chunk.*; +import com.mithrilmania.blocktopograph.chunk.Chunk; +import com.mithrilmania.blocktopograph.chunk.NBTChunkData; import com.mithrilmania.blocktopograph.map.marker.AbstractMarker; import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; import com.mithrilmania.blocktopograph.nbt.tags.FloatTag; @@ -13,6 +16,7 @@ import com.mithrilmania.blocktopograph.nbt.tags.StringTag; import com.mithrilmania.blocktopograph.nbt.tags.Tag; +import java.lang.ref.WeakReference; import java.util.Collection; import java.util.List; @@ -21,28 +25,29 @@ */ public class MarkerAsyncTask extends AsyncTask { - private final WorldActivityInterface worldProvider; - private final ChunkManager chunkManager; + private final WeakReference worldProvider; private final int minChunkX, minChunkZ, maxChunkX, maxChunkZ; + private final Dimension dimension; - public MarkerAsyncTask(WorldActivityInterface worldProvider, ChunkManager chunkManager, int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ){ + public MarkerAsyncTask(WorldActivityInterface worldProvider, int minChunkX, int minChunkZ, + int maxChunkX, int maxChunkZ, Dimension dimension) { this.minChunkX = minChunkX; this.minChunkZ = minChunkZ; this.maxChunkX = maxChunkX; this.maxChunkZ = maxChunkZ; + this.dimension = dimension; - this.worldProvider = worldProvider; - this.chunkManager = chunkManager; + this.worldProvider = new WeakReference<>(worldProvider); } @Override protected Void doInBackground(Void... v) { int cX, cZ; - for(cZ = minChunkZ; cZ < maxChunkZ; cZ++){ - for(cX = minChunkX; cX < maxChunkX; cX++){ + for (cZ = minChunkZ; cZ < maxChunkZ; cZ++) { + for (cX = minChunkX; cX < maxChunkX; cX++) { loadEntityMarkers(cX, cZ); loadTileEntityMarkers(cX, cZ); loadCustomMarkers(cX, cZ); @@ -52,9 +57,10 @@ protected Void doInBackground(Void... v) { return null; } - private void loadEntityMarkers(int chunkX, int chunkZ){ + private void loadEntityMarkers(int chunkX, int chunkZ) { try { - Chunk chunk = chunkManager.getChunk(chunkX, chunkZ); + Chunk chunk = worldProvider.get().getWorld().getWorldData() + .getChunk(chunkX, chunkZ, dimension); NBTChunkData entityData = chunk.getEntity(); @@ -62,36 +68,44 @@ private void loadEntityMarkers(int chunkX, int chunkZ){ entityData.load(); - if(entityData.tags == null) return; + if (entityData.tags == null) return; for (Tag tag : entityData.tags) { - if (tag instanceof CompoundTag) { - CompoundTag compoundTag = (CompoundTag) tag; - //int id = ((IntTag) compoundTag.getChildTagByKey("id")).getValue(); - String tempName = compoundTag.getChildTagByKey("identifier").getValue().toString(); - tempName = tempName.replace("minecraft:",""); - tempName = tempName.substring(0, 1).toUpperCase() + tempName.substring(1); - int id = Entity.getEntity(tempName).id; - Entity e = Entity.getEntity(id & 0xff); - if (e != null && e.bitmap != null) { - List pos = ((ListTag) compoundTag.getChildTagByKey("Pos")).getValue(); - float xf = ((FloatTag) pos.get(0)).getValue(); - float yf = ((FloatTag) pos.get(1)).getValue(); - float zf = ((FloatTag) pos.get(2)).getValue(); - - this.publishProgress(new AbstractMarker(Math.round(xf), Math.round(yf), Math.round(zf), chunkManager.dimension, e, false)); + if (!(tag instanceof CompoundTag)) continue; + CompoundTag compoundTag = (CompoundTag) tag; + Entity e = null; + { + Tag idTag = compoundTag.getChildTagByKey("id"); + if (idTag instanceof IntTag) { + Integer id = ((IntTag) idTag).getValue(); + if (id != null) e = Entity.getEntity(id); } } + if (e == null) { + Tag idenTag = compoundTag.getChildTagByKey("identifier"); + if (idenTag instanceof StringTag) { + String identifier = ((StringTag) idenTag).getValue(); + if (identifier != null) e = Entity.getEntity(identifier); + } + } + if (e == null) e = Entity.UNKNOWN; + List pos = ((ListTag) compoundTag.getChildTagByKey("Pos")).getValue(); + float xf = ((FloatTag) pos.get(0)).getValue(); + float yf = ((FloatTag) pos.get(1)).getValue(); + float zf = ((FloatTag) pos.get(2)).getValue(); + + this.publishProgress(new AbstractMarker(Math.round(xf), Math.round(yf), Math.round(zf), dimension, e, false)); } - } catch (Exception e){ - Log.w(e.getMessage()); + } catch (Exception e) { + Log.d(this, e); } } - private void loadTileEntityMarkers(int chunkX, int chunkZ){ + private void loadTileEntityMarkers(int chunkX, int chunkZ) { try { - Chunk chunk = chunkManager.getChunk(chunkX, chunkZ); + Chunk chunk = worldProvider.get().getWorld().getWorldData() + .getChunk(chunkX, chunkZ, dimension); NBTChunkData tileEntityData = chunk.getBlockEntity(); @@ -99,7 +113,7 @@ private void loadTileEntityMarkers(int chunkX, int chunkZ){ tileEntityData.load(); - if(tileEntityData.tags == null) return; + if (tileEntityData.tags == null) return; for (Tag tag : tileEntityData.tags) { if (tag instanceof CompoundTag) { @@ -111,18 +125,19 @@ private void loadTileEntityMarkers(int chunkX, int chunkZ){ int eY = ((IntTag) compoundTag.getChildTagByKey("y")).getValue(); int eZ = ((IntTag) compoundTag.getChildTagByKey("z")).getValue(); - this.publishProgress(new AbstractMarker(Math.round(eX), Math.round(eY), Math.round(eZ), chunkManager.dimension, te, false)); + this.publishProgress(new AbstractMarker(Math.round(eX), Math.round(eY), Math.round(eZ), dimension, te, false)); } } } - } catch (Exception e){ - Log.w(e.getMessage()); + } catch (Exception e) { + Log.d(this, e); } } - private void loadCustomMarkers(int chunkX, int chunkZ){ - Collection chunk = worldProvider.getWorld().getMarkerManager() + private void loadCustomMarkers(int chunkX, int chunkZ) { + WorldActivityInterface wai = worldProvider.get(); + Collection chunk = wai.getWorld().getMarkerManager() .getMarkersOfChunk(chunkX, chunkZ); AbstractMarker[] markers = new AbstractMarker[chunk.size()]; this.publishProgress(chunk.toArray(markers)); @@ -130,8 +145,27 @@ private void loadCustomMarkers(int chunkX, int chunkZ){ @Override protected void onProgressUpdate(AbstractMarker... values) { - for(AbstractMarker marker : values){ - worldProvider.addMarker(marker); + WorldActivityInterface wai = worldProvider.get(); + + // Some of the marks may have been added to screen already, remove first. + // TODO: Why not just skipping them? + for (AbstractMarker marker : values) { + // 2019/2/27 fixing crash here. + // Fatal Exception: java.lang.IllegalStateException + // The specified child already has a parent. + // You must call removeView() on the child's parent first. + // com.qozix.tileview.markers.MarkerLayout.addMarker + // We found it caused by custom markers reusing issue. + // Entity and TileEntity marks are all newly created. + // So we're removing custom marks from parent if present. + + if (marker.view != null) { + ViewParent par = marker.view.getParent(); + if (par instanceof ViewGroup) + ((ViewGroup) par).removeView(marker.view); + } + + wai.addMarker(marker); } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerManager.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerManager.java index 2df8b669..15791ca2 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerManager.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/MarkerManager.java @@ -3,7 +3,7 @@ import android.util.LongSparseArray; import com.mithrilmania.blocktopograph.Log; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; import com.mithrilmania.blocktopograph.map.marker.AbstractMarker; import com.mithrilmania.blocktopograph.map.marker.CustomNamedBitmapProvider; import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; @@ -26,7 +26,6 @@ /** * TODO docs - * */ public class MarkerManager { @@ -51,6 +50,7 @@ public class MarkerManager { // // example: // 1 "Test \" marker" "default \" \"_ma 1 rker 1" 1234 64 4321 overworld ; + // Why bother inventing a format? private static final Pattern formatRegex = Pattern.compile("(\\d+)\\s+\"(?:(?:(.+?[^\\\\]))|)\"\\s+\"(?:(?:(.+?[^\\\\]))|)\"\\s+(\\d+?)\\s+(\\d+?)\\s+(\\d+?)\\s+(.+?)\\s*;"); @@ -62,12 +62,12 @@ public class MarkerManager { private boolean dirty; - public MarkerManager(File markerFile){ + public MarkerManager(File markerFile) { this.markerFile = markerFile; executorService = Executors.newSingleThreadExecutor(); } - public void load(){ + public void load() { executorService.submit(new Runnable() { @Override public void run() { @@ -76,31 +76,35 @@ public void run() { }); } - public void removeMarker(AbstractMarker marker, boolean dirty){ + private static long xzToKey(int x, int z) { + return (((long) x) << 32) | z; + } + + public void removeMarker(AbstractMarker marker, boolean dirty) { - long chunkKey = ChunkManager.xzToKey(marker.x >> 4, marker.z >> 4); + long chunkKey = xzToKey(marker.x >> 4, marker.z >> 4); Set chunk = chunks.get(chunkKey); - if(chunk != null) chunk.remove(marker); + if (chunk != null) chunk.remove(marker); //only set it to dirty if the marker is removed. this.dirty |= markers.remove(marker) && dirty; } - public void addMarker(AbstractMarker marker, boolean dirty){ + public void addMarker(AbstractMarker marker, boolean dirty) { markers.add(marker); - long chunkKey = ChunkManager.xzToKey(marker.x >> 4, marker.z >> 4); + long chunkKey = xzToKey(marker.x >> 4, marker.z >> 4); Set chunk = chunks.get(chunkKey); - if(chunk == null) chunks.put(chunkKey, chunk = new HashSet<>()); + if (chunk == null) chunks.put(chunkKey, chunk = new HashSet<>()); chunk.add(marker); this.dirty |= dirty; } - private synchronized Set loadFromFile(){ + private synchronized Set loadFromFile() { markers = new HashSet<>(); - if(this.markerFile.exists()) { + if (this.markerFile.exists()) { try { BufferedReader br = new BufferedReader(new FileReader(this.markerFile)); String line; @@ -130,7 +134,7 @@ private synchronized Set loadFromFile(){ } } catch (Exception e) { //ok, probably a comment or something, just ignore - Log.d("Invalid line in marker file: " + line); + Log.d(this, "Invalid line in marker file: " + line); } } br.close(); @@ -148,8 +152,8 @@ private synchronized Set loadFromFile(){ /** * Saves the current markers, if and only if the markers were changed. */ - public void save(){ - if(dirty) executorService.submit(new Runnable() { + public void save() { + if (dirty) executorService.submit(new Runnable() { @Override public void run() { MarkerManager.this.saveToFile(); @@ -158,15 +162,16 @@ public void run() { }); } - private synchronized void saveToFile(){ + private synchronized void saveToFile() { try { - if(markerFile.createNewFile()) Log.d("Created "+this.markerFile.getAbsolutePath()); + if (markerFile.createNewFile()) + Log.d(this, "Created " + this.markerFile.getAbsolutePath()); //append to file PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(this.markerFile, false))); - for(AbstractMarker marker : markers){ + for (AbstractMarker marker : markers) { out.format("1 \"%s\", \"%s\", %d %d %d %s ;\n", marker.getNamedBitmapProvider().getBitmapDisplayName().replace("\"", "\\\""), marker.getNamedBitmapProvider().getBitmapDataName().replace("\"", "\\\""), @@ -180,27 +185,27 @@ private synchronized void saveToFile(){ } } - public Collection getMarkers(){ + public Collection getMarkers() { return Collections.unmodifiableSet(markers); } - public Collection getMarkersOfChunk(int chunkX, int chunkZ){ - long key = ChunkManager.xzToKey(chunkX, chunkZ); + public Collection getMarkersOfChunk(int chunkX, int chunkZ) { + long key = xzToKey(chunkX, chunkZ); Set chunk = chunks.get(key); - if(chunk == null) chunks.put(key, chunk = new HashSet<>()); + if (chunk == null) chunks.put(key, chunk = new HashSet<>()); return chunk; } - public static AbstractMarker markerFromData(String displayName, String iconName, int x, int y, int z, Dimension dimension){ + public static AbstractMarker markerFromData(String displayName, String iconName, int x, int y, int z, Dimension dimension) { - NamedBitmapProvider nbp = Block.getByDataName(iconName); - if(nbp == null || nbp.getBitmap() == null) nbp = Entity.getEntity(iconName); - if(nbp == null || nbp.getBitmap() == null) nbp = TileEntity.getTileEntity(iconName); - if(nbp == null || nbp.getBitmap() == null) nbp = CustomIcon.getCustomIcon(iconName); - if(nbp == null || nbp.getBitmap() == null) nbp = CustomIcon.DEFAULT_MARKER; + NamedBitmapProvider nbp = KnownBlockRepr.getByDataName(iconName); + if (nbp == null || nbp.getBitmap() == null) nbp = Entity.getEntity(iconName); + if (nbp == null || nbp.getBitmap() == null) nbp = TileEntity.getTileEntity(iconName); + if (nbp == null || nbp.getBitmap() == null) nbp = CustomIcon.getCustomIcon(iconName); + if (nbp == null || nbp.getBitmap() == null) nbp = CustomIcon.DEFAULT_MARKER; return new AbstractMarker(x, y, z, dimension, - new CustomNamedBitmapProvider(nbp, displayName), true); + new CustomNamedBitmapProvider(nbp, displayName), true); } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/OpenLongPressMenuHandler.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/OpenLongPressMenuHandler.java new file mode 100644 index 00000000..98adb766 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/OpenLongPressMenuHandler.java @@ -0,0 +1,7 @@ +package com.mithrilmania.blocktopograph.map; + +public interface OpenLongPressMenuHandler { + + void open(); + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/Player.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/Player.java new file mode 100644 index 00000000..b50d1834 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/Player.java @@ -0,0 +1,59 @@ +package com.mithrilmania.blocktopograph.map; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.util.math.DimensionVector3; + + +public class Player { + + public static final String LOCAL_PLAYER_NAME = "~local_player"; + + private final boolean isLocal; + private String dbName; + private DimensionVector3 position; + + private Player(boolean isLocal, String dbName) { + this.isLocal = isLocal; + this.dbName = dbName; + } + + @NonNull + + public static Player localPlayer() { + return new Player(true, LOCAL_PLAYER_NAME); + } + + @NonNull + + public static Player networkPlayer(String dbName) { + return new Player(false, dbName); + } + + public boolean isLocal() { + return isLocal; + } + + public String getDbName() { + return dbName; + } + + public DimensionVector3 getPosition() { + return position; + } + + public String getPositionDescription(Context context) { + if (position == null) + return context.getString(R.string.map_locator_player_pos_unknown); + return context.getString(R.string.player_position_desc, + Math.round(position.x), Math.round(position.y), + Math.round(position.z), context.getString(position.dimension.getName())); + } + + public void setPosition(DimensionVector3 position) { + this.position = position; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/TileEntity.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/TileEntity.java index 75530f07..5120c971 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/TileEntity.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/TileEntity.java @@ -1,8 +1,11 @@ package com.mithrilmania.blocktopograph.map; +import android.content.res.AssetManager; import android.graphics.Bitmap; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.block.ListingBlock; import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; @@ -12,41 +15,52 @@ public enum TileEntity implements NamedBitmapProviderHandle, NamedBitmapProvider { - CHEST(0, "Chest", "Chest", Block.B_54_0_CHEST), - TRAPPED_CHEST(1, "Trapped Chest", "TrappedChest", Block.B_146_0_TRAPPED_CHEST), - ENDER_CHEST(2, "Ender Chest", "EnderChest", Block.B_130_0_ENDER_CHEST), - MOB_SPAWNER(3, "Mob Spawner", "MobSpawner", Block.B_52_0_MOB_SPAWNER), - END_PORTAL(4, "End Portal", "EndPortal", Block.B_119_0_END_PORTAL), - BEACON(5, "Beacon", "Beacon", Block.B_138_0_BEACON); + CHEST(0, "Chest", "Chest", ListingBlock.B_54_CHEST), + TRAPPED_CHEST(1, "Trapped Chest", "TrappedChest", ListingBlock.B_146_TRAPPED_CHEST), + ENDER_CHEST(2, "Ender Chest", "EnderChest", ListingBlock.B_130_ENDER_CHEST), + MOB_SPAWNER(3, "Mob Spawner", "MobSpawner", ListingBlock.B_52_MOB_SPAWNER), + END_PORTAL(4, "End Portal", "EndPortal", ListingBlock.B_119_END_PORTAL), + BEACON(5, "Beacon", "Beacon", ListingBlock.B_138_BEACON); + private static final Map tileEntityMap; + private static final Map tileEntityByID; + public final int id; public final String displayName, dataName; - public final Block block; + static { + tileEntityMap = new HashMap<>(); + tileEntityByID = new HashMap<>(); + for (TileEntity e : TileEntity.values()) { + tileEntityMap.put(e.dataName, e); + tileEntityByID.put(e.id, e); + } + } + + public final ListingBlock block; + public Bitmap icon; - TileEntity(int id, String displayName, String dataName, Block block){ + TileEntity(int id, String displayName, String dataName, ListingBlock block) { this.id = id; this.displayName = displayName; this.dataName = dataName; this.block = block; } - @Override - public Bitmap getBitmap(){ - return block.bitmap; + static public synchronized void loadIcons(AssetManager assMan) { + for (TileEntity entity : values()) + if (entity.icon == null) + entity.icon = Bitmap.createScaledBitmap(entity.block.getIcon(assMan), + 36, 36, false); } - @NonNull - @Override - public NamedBitmapProvider getNamedBitmapProvider(){ - return this; + public static TileEntity getTileEntity(int id) { + return tileEntityByID.get(id); } - @NonNull - @Override - public String getBitmapDisplayName(){ - return this.displayName; + public static TileEntity getTileEntity(String dataName) { + return tileEntityMap.get(dataName); } @NonNull @@ -55,25 +69,22 @@ public String getBitmapDataName() { return this.dataName; } - private static final Map tileEntityMap; - private static final Map tileEntityByID; - - static { - tileEntityMap = new HashMap<>(); - tileEntityByID = new HashMap<>(); - for(TileEntity e : TileEntity.values()){ - tileEntityMap.put(e.dataName, e); - tileEntityByID.put(e.id, e); - } + @Override + public Bitmap getBitmap() { + return icon; } - public static TileEntity getTileEntity(int id){ - return tileEntityByID.get(id); + @NonNull + @Override + public NamedBitmapProvider getNamedBitmapProvider() { + return this; } - public static TileEntity getTileEntity(String dataName){ - return tileEntityMap.get(dataName); + @NonNull + @Override + public String getBitmapDisplayName() { + return this.displayName; } - + } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChBiomeEdit.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChBiomeEdit.java new file mode 100644 index 00000000..cc8b8ea1 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChBiomeEdit.java @@ -0,0 +1,30 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.chunk.Chunk; +import com.mithrilmania.blocktopograph.map.Biome; + + +public class ChBiomeEdit implements EditTarget.RandomAccessEdit { + + @Nullable + private Biome mFrom; + + @NonNull + private Biome mTo; + + ChBiomeEdit(@Nullable Biome fromBiome, @NonNull Biome toBiome) { + mFrom = fromBiome; + mTo = toBiome; + } + + @Override + public int edit(Chunk chunk, int x, int y, int z) { + if (mFrom == null || chunk.getBiome(x, z) == mFrom.id) + chunk.setBiome(x, z, mTo.id); + return 0; + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChBiomeFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChBiomeFragment.java new file mode 100644 index 00000000..556eb60f --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChBiomeFragment.java @@ -0,0 +1,119 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RadioGroup; + +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.DialogFragment; + +import com.mithrilmania.blocktopograph.BiomeSelectDialog; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.databinding.FragChBiomeBinding; +import com.mithrilmania.blocktopograph.map.Biome; +import com.mithrilmania.blocktopograph.map.selection.SelectionMenuFragment; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.io.Serializable; + +import static android.app.Activity.RESULT_OK; + +public final class ChBiomeFragment extends DialogFragment { + + public static final String KEY_FROM = "from"; + public static final String KEY_TO = "to"; + private static final int REQUEST_CODE_FOR = 2012; + private static final int REQUEST_CODE_TO = 2013; + private FragChBiomeBinding mBinding; + private SelectionMenuFragment.EditFunctionEntry mEntry; + + public static ChBiomeFragment newInstance(SelectionMenuFragment.EditFunctionEntry entry) { + ChBiomeFragment fragment = new ChBiomeFragment(); + fragment.mEntry = entry; + return fragment; + } + + private void onChangeForCheckedChanged(@NonNull RadioGroup group, @IdRes int checkedId) { + mBinding.biomeView.getRoot().setVisibility( + checkedId == R.id.biome_for_specific ? View.VISIBLE : View.GONE); + } + + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate(inflater, R.layout.frag_ch_biome, container, false); + mBinding.changeFor.setOnCheckedChangeListener(this::onChangeForCheckedChanged); + mBinding.biomeView.getRoot().setOnClickListener(v -> + startActivityForResult(new Intent(getActivity(), BiomeSelectDialog.class), REQUEST_CODE_FOR)); + mBinding.biomeReplace.getRoot().setOnClickListener(v -> + startActivityForResult(new Intent(getActivity(), BiomeSelectDialog.class), REQUEST_CODE_TO)); + UiUtil.blendBlockColor(mBinding.biomeView.getRoot(), Biome.PLAINS); + mBinding.biomeView.setBiome(Biome.PLAINS); + mBinding.biomeView.getRoot().setVisibility(View.GONE); + UiUtil.blendBlockColor(mBinding.biomeReplace.getRoot(), Biome.JUNGLE); + mBinding.biomeReplace.setBiome(Biome.JUNGLE); + View root = mBinding.getRoot(); + Dialog dialog = getDialog(); + if (dialog instanceof AlertDialog) { + ((AlertDialog) dialog).setView(root); + } + return root; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + Context context = requireContext(); + return new AlertDialog.Builder(context) + .setTitle(R.string.map_edit_func_chbiome) + .setPositiveButton(android.R.string.ok, this::onClickOk) + .setNegativeButton(android.R.string.cancel, null) + .create(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + switch (requestCode) { + case REQUEST_CODE_FOR: + case REQUEST_CODE_TO: + if (resultCode == RESULT_OK && data != null) { + Serializable ser = data.getSerializableExtra(BiomeSelectDialog.KEY_BIOME); + if (ser instanceof Biome) { + Biome biome = (Biome) ser; + switch (requestCode) { + case REQUEST_CODE_FOR: + UiUtil.blendBlockColor(mBinding.biomeView.getRoot(), biome); + mBinding.biomeView.setBiome(biome); + break; + case REQUEST_CODE_TO: + UiUtil.blendBlockColor(mBinding.biomeReplace.getRoot(), biome); + mBinding.biomeReplace.setBiome(biome); + break; + } + } + } + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + private void onClickOk(DialogInterface dia, int i) { + Bundle bundle = new Bundle(); + bundle.putSerializable(KEY_FROM, + mBinding.changeFor.getCheckedRadioButtonId() == R.id.biome_for_all ? + null : mBinding.biomeView.getBiome()); + Biome biomeTo = mBinding.biomeReplace.getBiome(); + bundle.putSerializable(KEY_TO, biomeTo == null ? Biome.PLAINS : biomeTo); + mEntry.invokeEditFunction(EditFunction.CHBIOME, bundle); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChunkBasedEditResult.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChunkBasedEditResult.java new file mode 100644 index 00000000..6253b834 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/ChunkBasedEditResult.java @@ -0,0 +1,25 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import com.mithrilmania.blocktopograph.map.Dimension; + +/** + * Used to publish result for every chunks in chunk-cased edit. + */ +public class ChunkBasedEditResult { + + public int x; + + public int z; + + public Dimension dimension; + + public EditResultCode resultCode; + + public ChunkBasedEditResult(int x, int z, Dimension dimension, EditResultCode resultCode) { + this.x = x; + this.z = z; + this.dimension = dimension; + this.resultCode = resultCode; + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/DchunkEdit.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/DchunkEdit.java new file mode 100644 index 00000000..7192f406 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/DchunkEdit.java @@ -0,0 +1,29 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.chunk.Chunk; + +public class DchunkEdit implements EditTarget.ChunkBasedEdit { + + private static final int MAX_EXCEPTION = 5; + + private int exceptionCount; + + public DchunkEdit() { + exceptionCount = 0; + } + + @Override + public int edit(Chunk chunk, int fromX, int toX, int fromY, int toY, int fromZ, int toZ) { + try { + chunk.deleteThis(); + } catch (Exception e) { + if (exceptionCount < MAX_EXCEPTION) { + Log.d(this, e); + exceptionCount++; + } + return -1; + } + return 0; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditFunction.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditFunction.java new file mode 100644 index 00000000..44f589d1 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditFunction.java @@ -0,0 +1,9 @@ +package com.mithrilmania.blocktopograph.map.edit; + +public enum EditFunction { + LAMPSHADE, + SNR, + DCHUNK, + CHBIOME, + PICER +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditResultCode.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditResultCode.java new file mode 100644 index 00000000..ce81dacf --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditResultCode.java @@ -0,0 +1,5 @@ +package com.mithrilmania.blocktopograph.map.edit; + +public enum EditResultCode { + SUCCESS, DB_ERROR, GENERAL_FAILURE, PARTIALLY_FAILED, QUIT_TOO_MANY_ERROR +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditTarget.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditTarget.java new file mode 100644 index 00000000..ba7caa0f --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/EditTarget.java @@ -0,0 +1,49 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Chunk; + + +public abstract class EditTarget { + + protected int mMaxError = 10; + + protected final boolean mIsChunkAware; + @NonNull + protected final WorldData mWorldData; + + protected EditTarget(boolean isChunkAware, @NonNull WorldData worldData) { + mIsChunkAware = isChunkAware; + mWorldData = worldData; + } + + public abstract EditResultCode forEachXyz(RandomAccessEdit edit); + + public abstract EditResultCode forEachXz(RandomAccessEdit edit); + + public abstract EditResultCode forEachChunk(ChunkBasedEdit edit); + + public final void setMaxError(int maxError) { + mMaxError = maxError; + } + + + public final boolean isChunkAware() { + return mIsChunkAware; + } + + public interface RandomAccessEdit { + + int edit(Chunk chunk, int x, int y, int z); + + } + + public interface ChunkBasedEdit { + + int edit(Chunk chunk, int fromX, int toX, int fromY, int toY, int fromZ, int toZ); + + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/RectEditTarget.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/RectEditTarget.java new file mode 100644 index 00000000..0f4c3571 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/RectEditTarget.java @@ -0,0 +1,145 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import android.annotation.SuppressLint; +import android.graphics.Rect; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Chunk; +import com.mithrilmania.blocktopograph.chunk.Version; +import com.mithrilmania.blocktopograph.map.Dimension; + + +public class RectEditTarget extends EditTarget { + + @NonNull + private final Rect mArea; + + private final int yLowest; + + private final int yHighest; + + @NonNull + private final Dimension dimension; + + public RectEditTarget(@NonNull WorldData worldData, @NonNull Rect area, @NonNull Dimension dimension) { + super(true, worldData); + mArea = new Rect(area); + mArea.right--; + mArea.bottom--; + yLowest = 0; + yHighest = 255; + this.dimension = dimension; + } + + @Override + public EditResultCode forEachXyz(RandomAccessEdit edit) { + return forEach(false, false, null, edit); + } + + @Override + public EditResultCode forEachXz(RandomAccessEdit edit) { + return forEach(false, true, null, edit); + } + + @Override + public EditResultCode forEachChunk(ChunkBasedEdit edit) { + return forEach(true, false, edit, null); + } + + @SuppressLint("DefaultLocale") + private EditResultCode forEach(boolean chunkBased, boolean is2d, + @Nullable ChunkBasedEdit chunkBasedEdit, + @Nullable RandomAccessEdit randomAccessEdit) { + + int exceptionCount = 0; + + int chunkMinX = mArea.left >> 4; + int chunkMaxX = mArea.right >> 4; + int chunkMinZ = mArea.top >> 4; + int chunkMaxZ = mArea.bottom >> 4; + + // Cache should not be used till end. + + for (int chunkX = chunkMinX; chunkX <= chunkMaxX; chunkX++) { + int innerMinX = (chunkX == chunkMinX) ? (mArea.left & 0xf) : 0; + int innerMaxX = (chunkX == chunkMaxX) ? (mArea.right & 0xf) : 15; + + for (int chunkZ = chunkMinZ; chunkZ <= chunkMaxZ; chunkZ++) { + int innerMinZ = (chunkZ == chunkMinZ) ? (mArea.top & 0xf) : 0; + int innerMaxZ = (chunkZ == chunkMaxZ) ? (mArea.bottom & 0xf) : 15; + + Chunk chunk = mWorldData.getChunkStreaming(chunkX, chunkZ, dimension, false, Version.V1_2_PLUS); + + if (chunkBased) { + int result = chunkBasedEdit.edit(chunk, innerMinX, innerMaxX, yLowest, yHighest, innerMinZ, innerMaxZ); + if (result != 0) { + if (exceptionCount < 5 || exceptionCount > mMaxError) { + Log.d(this, String.format( + "Failed with chunk (%d,%d), code %d", + chunkX, chunkZ, result)); + if (exceptionCount > mMaxError) + return EditResultCode.QUIT_TOO_MANY_ERROR; + exceptionCount++; + } + } + } else { + boolean supportHightMap = chunk.supportsHeightMap(); + + for (int innerX = innerMinX; innerX <= innerMaxX; innerX++) { + for (int innerZ = innerMinZ; innerZ <= innerMaxZ; innerZ++) { + + if (is2d) { + int result = randomAccessEdit.edit(chunk, innerX, 0, innerZ); + if (result != 0) { + if (exceptionCount < 5 || exceptionCount > mMaxError) { + Log.d(this, String.format( + "Failed with chunk (%d,%d), rel (%d,%d), code %d", + chunkX, chunkZ, innerX, innerZ, result)); + if (exceptionCount > mMaxError) + return EditResultCode.QUIT_TOO_MANY_ERROR; + exceptionCount++; + } + } + } else { + + //Math.min(yHighest, chunk.getHeightMapValue(innerX, innerZ) - 1) + //: yHighest; + for (int y = yLowest; y <= yHighest; y++) { + int result = randomAccessEdit.edit(chunk, innerX, y, innerZ); + if (result != 0) { + if (exceptionCount < 5 || exceptionCount > mMaxError) { + Log.d(this, String.format( + "Failed with chunk (%d,%d), rel (%d,%d,%d), code %d", + chunkX, chunkZ, innerX, y, innerZ, result)); + if (exceptionCount > mMaxError) + return EditResultCode.QUIT_TOO_MANY_ERROR; + exceptionCount++; + } + } + }// End for y + + } + }// End for innerZ + }// End for innerX + } + + try { + chunk.save(); + } catch (Exception e) { + if (exceptionCount < 5 || exceptionCount > mMaxError) { + Log.d(this, e); + if (exceptionCount > mMaxError) return EditResultCode.QUIT_TOO_MANY_ERROR; + exceptionCount++; + } + } + }// End for ChunkZ + }// End for ChunkX + + mWorldData.resetCache(); + return exceptionCount > 0 ? EditResultCode.PARTIALLY_FAILED : EditResultCode.SUCCESS; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SearchAndReplaceFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SearchAndReplaceFragment.java new file mode 100644 index 00000000..e86ee3c3 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SearchAndReplaceFragment.java @@ -0,0 +1,300 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.DialogFragment; + +import com.jbvincey.nestedradiobutton.NestedRadioGroupManager; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.OldBlockRegistry; +import com.mithrilmania.blocktopograph.databinding.FragSerachAndReplaceBinding; +import com.mithrilmania.blocktopograph.databinding.IncludeBlockBinding; +import com.mithrilmania.blocktopograph.flat.PickBlockActivity; +import com.mithrilmania.blocktopograph.map.selection.SelectionMenuFragment; +import com.mithrilmania.blocktopograph.util.UiUtil; +import com.tomergoldst.tooltips.ToolTip; +import com.tomergoldst.tooltips.ToolTipsManager; + +import java.io.Serializable; + +import static android.app.Activity.RESULT_OK; + +public class SearchAndReplaceFragment extends DialogFragment { + + public static final String CONFIG = "config"; + private static final int REQUEST_CODE = 2012; + private static final int[] REQ_OFFSET_IDS = { + R.id.search_block_any, R.id.search_block_bg, + R.id.search_block_fg, R.id.replace_block_any, + R.id.replace_block_bg, R.id.replace_block_fg + }; + private FragSerachAndReplaceBinding mBinding; + private SelectionMenuFragment.EditFunctionEntry mEntry; + private ToolTipsManager mToolTipsManager; + private OldBlockRegistry registry; + + public static SearchAndReplaceFragment newInstance(OldBlockRegistry registry, SelectionMenuFragment.EditFunctionEntry entry) { + SearchAndReplaceFragment fragment = new SearchAndReplaceFragment(); + fragment.mEntry = entry; + fragment.registry = registry; + return fragment; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate(inflater, R.layout.frag_serach_and_replace, container, false); + // Saved instance has highest priority to be recovered. + Serializable ser; + if (savedInstanceState != null && (ser = savedInstanceState.getSerializable(CONFIG)) instanceof SnrConfig) { + SnrConfig cfg = (SnrConfig) ser; + recoverSearchIn(cfg.searchMode); + recoverPlaceIn(cfg.placeMode); + switch (cfg.searchMode) { + case 1: + case 2: + case 3: + recoverBlock(mBinding.searchBlockAny, cfg.searchBlockMain); + break; + case 4: + recoverBlock(mBinding.searchBlockBg, cfg.searchBlockSub); + recoverBlock(mBinding.searchBlockFg, cfg.searchBlockMain); + break; + } + switch (cfg.placeMode) { + case 1: + case 2: + recoverBlock(mBinding.replaceBlockAny, cfg.placeOldBlockMain); + break; + case 3: + recoverBlock(mBinding.replaceBlockBg, cfg.placeOldBlockSub); + recoverBlock(mBinding.replaceBlockFg, cfg.placeOldBlockMain); + } + //mBinding.cbIgsub.setChecked(cfg.ignoreSubId); + } else { + setBlockToItem(mBinding.searchBlockAny, BlockTemplates.getOfType("minecraft:grass")[0]); + setBlockToItem(mBinding.searchBlockBg, BlockTemplates.getOfType("minecraft:air")[0]); + setBlockToItem(mBinding.searchBlockFg, BlockTemplates.getOfType("minecraft:grass")[0]); + setBlockToItem(mBinding.replaceBlockAny, BlockTemplates.getOfType("minecraft:glass")[0]); + setBlockToItem(mBinding.replaceBlockFg, BlockTemplates.getOfType("minecraft:glass")[0]); + setBlockToItem(mBinding.replaceBlockBg, BlockTemplates.getOfType("minecraft:water")[0]); + } + + mBinding.searchIn.setOnCheckedChangeListener(this::onCheckedChanged); + mBinding.placeIn.setOnCheckedChangeListener(this::onCheckedChanged); + mBinding.searchBlockAny.getRoot().setOnClickListener(this::onBlockItemClick); + mBinding.searchBlockBg.getRoot().setOnClickListener(this::onBlockItemClick); + mBinding.searchBlockFg.getRoot().setOnClickListener(this::onBlockItemClick); + mBinding.replaceBlockAny.getRoot().setOnClickListener(this::onBlockItemClick); + mBinding.replaceBlockBg.getRoot().setOnClickListener(this::onBlockItemClick); + mBinding.replaceBlockFg.getRoot().setOnClickListener(this::onBlockItemClick); + mBinding.ok.setOnClickListener(this::onClickOk); + mBinding.help.setOnClickListener(this::onClickHelpMain); + mToolTipsManager = new ToolTipsManager(); + View root = mBinding.getRoot(); + Dialog dialog = getDialog(); + if (dialog instanceof AlertDialog) { + ((AlertDialog) dialog).setView(root); + } + return root; + } + + private void onClickHelpMain(@NonNull View view) { + if (mToolTipsManager.findAndDismiss(view)) return; + ToolTip.Builder builder = new ToolTip.Builder( + view.getContext(), view, mBinding.frameMain, + getString(R.string.map_edit_snr_help_background), ToolTip.POSITION_BELOW) + .setAlign(ToolTip.ALIGN_LEFT); + mToolTipsManager.show(builder.build()); + } + + private int getSearchInCode() { + if (mBinding.rbSearchBg.isChecked()) return 1; + if (mBinding.rbSearchFg.isChecked()) return 2; + if (mBinding.rbSearchOr.isChecked()) return 3; + if (mBinding.rbSearchBoth.isChecked()) return 4; + return 0; + } + + private int getPlaceInCode() { + if (mBinding.rbPlaceBg.isChecked()) return 1; + if (mBinding.rbPlaceFg.isChecked()) return 2; + if (mBinding.rbPlaceBoth.isChecked()) return 3; + return 0; + } + + private void recoverSearchIn(int code) { + switch (code) { + case 1: + mBinding.rbSearchBg.setChecked(true); + break; + case 2: + mBinding.rbSearchFg.setChecked(true); + break; + case 3: + mBinding.rbSearchOr.setChecked(true); + break; + case 4: + mBinding.rbSearchBoth.setChecked(true); + break; + } + } + + private void recoverPlaceIn(int code) { + switch (code) { + case 1: + mBinding.rbPlaceBg.setChecked(true); + break; + case 2: + mBinding.rbPlaceFg.setChecked(true); + break; + case 3: + mBinding.rbPlaceBoth.setChecked(true); + break; + } + } + + private void recoverBlock(@NonNull IncludeBlockBinding item, @Nullable Serializable data) { + setBlockToItem(item, data instanceof BlockTemplate ? (BlockTemplate) data : BlockTemplates.getAirTemplate()); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + writeToBundle(outState); + super.onSaveInstanceState(outState); + } + + private void writeToBundle(@NonNull Bundle bundle) { + SnrConfig cfg = new SnrConfig(); + cfg.searchMode = getSearchInCode(); + cfg.placeMode = getPlaceInCode(); + switch (cfg.searchMode) { + case 1: + case 2: + case 3: + cfg.searchBlockMain = new SnrConfig.SearchConditionBlock( + mBinding.searchBlockAny.getBlockTemplate().getBlock(), false, true); + break; + case 4: + cfg.searchBlockMain = new SnrConfig.SearchConditionBlock( + mBinding.searchBlockFg.getBlockTemplate().getBlock(), false, true); + cfg.searchBlockSub = new SnrConfig.SearchConditionBlock( + mBinding.searchBlockBg.getBlockTemplate().getBlock(), false, true); + break; + } + switch (cfg.placeMode) { + case 1: + case 2: + cfg.placeOldBlockMain = mBinding.replaceBlockAny.getBlockTemplate().getBlock(); + break; + case 3: + cfg.placeOldBlockMain = mBinding.replaceBlockFg.getBlockTemplate().getBlock(); + cfg.placeOldBlockSub = mBinding.replaceBlockBg.getBlockTemplate().getBlock(); + break; + } + cfg.ignoreSubId = true;// mBinding.cbIgsub.isChecked(); + bundle.putSerializable(CONFIG, cfg); + } + + private void onBlockItemClick(@NonNull View view) { + int req = REQUEST_CODE; + int id = view.getId(); + for (int i = 0; i < REQ_OFFSET_IDS.length; i++) { + if (REQ_OFFSET_IDS[i] == id) { + req += i; + break; + } + } + startActivityForResult( + new Intent(view.getContext(), PickBlockActivity.class), req + ); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (resultCode == RESULT_OK && data != null) { + var blockTemplate = (BlockTemplate) data.getSerializableExtra(PickBlockActivity.EXTRA_KEY_BLOCK); + switch (requestCode - REQUEST_CODE) { + case 0: + setBlockToItem(mBinding.searchBlockAny, blockTemplate); + break; + case 1: + setBlockToItem(mBinding.searchBlockBg, blockTemplate); + break; + case 2: + setBlockToItem(mBinding.searchBlockFg, blockTemplate); + break; + case 3: + setBlockToItem(mBinding.replaceBlockAny, blockTemplate); + break; + case 4: + setBlockToItem(mBinding.replaceBlockBg, blockTemplate); + break; + case 5: + setBlockToItem(mBinding.replaceBlockFg, blockTemplate); + break; + } + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + private void setBlockToItem(@NonNull IncludeBlockBinding item, @NonNull BlockTemplate template) { + item.icon.setImageBitmap(template.getIcon().getIcon(getContext())); + UiUtil.blendBlockColor(item.getRoot(), template); + item.setBlockTemplate(template); + } + + private void onClickOk(View view) { + Bundle bundle = new Bundle(); + writeToBundle(bundle); + mEntry.invokeEditFunction(EditFunction.SNR, bundle); + dismiss(); + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + Context context = requireContext(); + return new AlertDialog.Builder(context) + .setTitle(R.string.map_edit_func_snr) + .create(); + } + + private void onCheckedChanged(@NonNull NestedRadioGroupManager group, @IdRes int checkedId) { + switch (checkedId) { + case R.id.rb_search_both: + mBinding.frameSearchTwo.setVisibility(View.VISIBLE); + mBinding.frameSearchOne.setVisibility(View.GONE); + break; + case R.id.rb_search_bg: + case R.id.rb_search_fg: + case R.id.rb_search_or: + mBinding.frameSearchTwo.setVisibility(View.GONE); + mBinding.frameSearchOne.setVisibility(View.VISIBLE); + break; + case R.id.rb_place_both: + mBinding.framePlaceTwo.setVisibility(View.VISIBLE); + mBinding.framePlaceOne.setVisibility(View.GONE); + break; + case R.id.rb_place_bg: + case R.id.rb_place_fg: + mBinding.framePlaceTwo.setVisibility(View.GONE); + mBinding.framePlaceOne.setVisibility(View.VISIBLE); + break; + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SelectionBasedContextFreeEditTask.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SelectionBasedContextFreeEditTask.java new file mode 100644 index 00000000..69b92384 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SelectionBasedContextFreeEditTask.java @@ -0,0 +1,153 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import android.app.Activity; +import android.content.DialogInterface; +import android.os.AsyncTask; +import android.os.Bundle; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; + +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.OldBlockRegistry; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.map.Biome; +import com.mithrilmania.blocktopograph.map.MapFragment; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.io.Serializable; +import java.lang.ref.WeakReference; + +public class SelectionBasedContextFreeEditTask extends + AsyncTask { + + @NonNull + private final EditFunction mFunction; + + @Nullable + private Bundle mArgs; + + @NonNull + private final WeakReference mOwner; + + @NonNull + private final OldBlockRegistry registry; + + private AlertDialog mWaitDialog; + + public SelectionBasedContextFreeEditTask( + @NonNull EditFunction func, @Nullable Bundle args, @NonNull MapFragment owner, + @NonNull OldBlockRegistry registry) { + mFunction = func; + mArgs = args; + this.registry = registry; + mOwner = new WeakReference<>(owner); + } + + @Override + protected void onPreExecute() { + MapFragment owner = mOwner.get(); + Activity activity; + if (owner == null || (activity = owner.getActivity()) == null) return; + mWaitDialog = UiUtil.buildProgressWaitDialog( + activity, R.string.general_please_wait, this::onCancel + ); + mWaitDialog.show(); + owner.world.setHaveBackgroundJob(true); + } + + @Override + protected EditResultCode doInBackground(EditTarget... editTargets) { + + switch (mFunction) { + case LAMPSHADE: { + SnrConfig cfg = new SnrConfig(); + cfg.searchMode = 2; + cfg.placeMode = 1; + cfg.searchBlockMain = new SnrConfig.SearchConditionBlock(BlockTemplates.getOfType("minecraft:torch")[0].getBlock(), true, true); + cfg.placeOldBlockMain = BlockTemplates.getOfType("minecraft:glass")[0].getBlock(); + cfg.ignoreSubId = true; + return doSnr(cfg, editTargets); + } + case SNR: { + Serializable ser; + if (mArgs == null || !((ser = mArgs.getSerializable(SearchAndReplaceFragment.CONFIG)) instanceof SnrConfig)) + return EditResultCode.GENERAL_FAILURE; + return doSnr((SnrConfig) ser, editTargets); + } + case DCHUNK: + return doDchunk(editTargets); + case CHBIOME: { + Serializable serFrom, serTo; + if (mArgs == null || !((serTo = mArgs.getSerializable(ChBiomeFragment.KEY_TO)) instanceof Biome)) + return EditResultCode.GENERAL_FAILURE; + serFrom = mArgs.getSerializable(ChBiomeFragment.KEY_FROM); + return doChBiome(serFrom instanceof Biome ? (Biome) serFrom : null, (Biome) serTo, editTargets); + } + } + return null; + } + + private EditResultCode doSnr(SnrConfig cfg, @NonNull EditTarget... editTargets) { + SnrEdit edit = new SnrEdit(cfg); + for (EditTarget editTarget : editTargets) { + editTarget.setMaxError(Integer.MAX_VALUE); + editTarget.forEachXyz(edit); + } + return EditResultCode.SUCCESS; + } + + private EditResultCode doDchunk(@NonNull EditTarget... editTargets) { + DchunkEdit edit = new DchunkEdit(); + for (EditTarget editTarget : editTargets) { + editTarget.setMaxError(Integer.MAX_VALUE); + editTarget.forEachChunk(edit); + } + return EditResultCode.SUCCESS; + } + + private EditResultCode doChBiome(@Nullable Biome from, @NonNull Biome to, + @NonNull EditTarget... editTargets) { + ChBiomeEdit edit = new ChBiomeEdit(from, to); + for (EditTarget editTarget : editTargets) { + editTarget.setMaxError(Integer.MAX_VALUE); + editTarget.forEachXz(edit); + } + return EditResultCode.SUCCESS; + } + + private void onCancel(DialogInterface dialogInterface) { + cancel(true); + mWaitDialog = null; + MapFragment owner; + if ((owner = mOwner.get()) != null) + owner.world.setHaveBackgroundJob(false); + } + + @Override + protected void onPostExecute(@Nullable EditResultCode editResultCode) { + if (mWaitDialog != null) { + mWaitDialog.dismiss(); + } + MapFragment owner = mOwner.get(); + Activity activity; + if (owner != null && (activity = owner.getActivity()) != null) { + owner.world.setHaveBackgroundJob(false); + if (editResultCode == null) + return; + switch (editResultCode) { + case SUCCESS: + Toast.makeText(activity, R.string.general_done, Toast.LENGTH_SHORT).show(); + owner.refreshAfterEdit(); + break; + case DB_ERROR: + default: + Toast.makeText(activity, R.string.general_failed, Toast.LENGTH_SHORT).show(); + break; + } + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SnrConfig.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SnrConfig.java new file mode 100644 index 00000000..b4b98850 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SnrConfig.java @@ -0,0 +1,81 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import android.util.Pair; + +import androidx.annotation.NonNull; + +import com.google.common.collect.Streams; +import com.mithrilmania.blocktopograph.block.Block; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; + +public class SnrConfig implements Serializable { + + private static final String KEY_SEARCH_IN = "search_in"; + private static final String KEY_PLACE_IN = "place_in"; + private static final String KEY_SEARCH_ANY = "search_any"; + private static final String KEY_SEARCH_BG = "search_bg"; + private static final String KEY_SEARCH_FG = "search_fg"; + private static final String KEY_PLACE_ANY = "place_any"; + private static final String KEY_PLACE_BG = "place_bg"; + private static final String KEY_PLACE_FG = "place_fg"; + + public boolean ignoreSubId; + public int searchMode; + public int placeMode; + public SearchConditionBlock searchBlockMain; + public SearchConditionBlock searchBlockSub; + public Block placeOldBlockMain; + public Block placeOldBlockSub; + + //savedInstanceState.getInt(KEY_SEARCH_IN, 0) + //savedInstanceState.getInt(KEY_PLACE_IN, 0) + //savedInstanceState.getSerializable(KEY_SEARCH_ANY) + //savedInstanceState.getSerializable(KEY_SEARCH_BG) + //savedInstanceState.getSerializable(KEY_SEARCH_FG) + //savedInstanceState.getSerializable(KEY_PLACE_ANY) + //savedInstanceState.getSerializable(KEY_PLACE_BG) + //savedInstanceState.getSerializable(KEY_PLACE_FG) + + +// bundle.putInt(KEY_SEARCH_IN, getSearchInCode()); +// bundle.putInt(KEY_PLACE_IN, getPlaceInCode()); +// bundle.putSerializable(KEY_SEARCH_ANY, mBinding.searchBlockAny.getBlock()); +// bundle.putSerializable(KEY_SEARCH_BG, mBinding.searchBlockBg.getBlock()); +// bundle.putSerializable(KEY_SEARCH_FG, mBinding.searchBlockFg.getBlock()); +// bundle.putSerializable(KEY_PLACE_ANY, mBinding.replaceBlockAny.getBlock()); +// bundle.putSerializable(KEY_PLACE_BG, mBinding.replaceBlockBg.getBlock()); +// bundle.putSerializable(KEY_PLACE_FG, mBinding.replaceBlockFg.getBlock()); + + public static class SearchConditionBlock implements Serializable { + private final Block examplar; + private final boolean matchNameOnly; + private final boolean allowExtraStates; + + public SearchConditionBlock(@NonNull Block block, boolean matchNameOnly, boolean allowExtraStates) { + this.examplar = block; + this.matchNameOnly = matchNameOnly; + this.allowExtraStates = allowExtraStates; + } + + public boolean matches(Block block) { + if (!examplar.getName().equals(block.getName())) return false; + var examplarKnownProperties = examplar.getKnownProperties(); + if (examplarKnownProperties != null && Streams.zip(Arrays.stream(examplarKnownProperties), + Arrays.stream(block.getKnownProperties()), Pair::new) + .anyMatch(pair -> pair.first != null && !Objects.equals(pair.first, pair.second))) { + return false; + } + var examplarCustomProperties = examplar.getCustomProperties(); + var blockCustomProperties = block.getCustomProperties(); + if (!allowExtraStates && blockCustomProperties.size() > examplarCustomProperties.size()) + return false; + for (var pair : examplarCustomProperties.entrySet()) + if (!Objects.equals(pair.getValue(), blockCustomProperties.get(pair.getKey()))) + return false; + return true; + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SnrEdit.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SnrEdit.java new file mode 100644 index 00000000..4d58f347 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/edit/SnrEdit.java @@ -0,0 +1,72 @@ +package com.mithrilmania.blocktopograph.map.edit; + +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.block.Block; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.chunk.Chunk; + + +public class SnrEdit implements EditTarget.RandomAccessEdit { + + private final SnrConfig config; + private SnrConfig.SearchConditionBlock b1; + private SnrConfig.SearchConditionBlock b2; + private Block b3; + private Block b4; + + SnrEdit(@NonNull SnrConfig cfg) { + config = cfg; + switch (cfg.searchMode) { + case 1: + case 2: + case 3: + b1 = cfg.searchBlockMain; + break; + case 4: + b1 = cfg.searchBlockMain; + b2 = cfg.searchBlockSub; + break; + } + switch (cfg.placeMode) { + case 1: + case 2: + b3 = cfg.placeOldBlockMain; + break; + case 3: + b3 = cfg.placeOldBlockMain; + b4 = cfg.placeOldBlockSub; + break; + } + } + + @Override + public int edit(Chunk chunk, int x, int y, int z) { + if ( + (config.searchMode == 1 && b1.matches(chunk.getBlock(x, y, z, 1)) + ) || (config.searchMode == 2 && b1.matches(chunk.getBlock(x, y, z)) + ) || (config.searchMode == 3 && ( + b1.matches(chunk.getBlock(x, y, z)) + || b1.matches(chunk.getBlock(x, y, z, 1))) + ) || (config.searchMode == 4 && ( + b1.matches(chunk.getBlock(x, y, z)) + && b2.matches(chunk.getBlock(x, y, z, 1))) + ) + ) { + switch (config.placeMode) { + case 1: + chunk.setBlock(x, y, z, 1, b3); + break; + case 2: + chunk.setBlock(x, y, z, 0, b3); + break; + case 3: + chunk.setBlock(x, y, z, 0, b3); + chunk.setBlock(x, y, z, 1, b4); + break; + } + } + return 0; + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/AdvancedLocatorFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/AdvancedLocatorFragment.java new file mode 100644 index 00000000..406353b4 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/AdvancedLocatorFragment.java @@ -0,0 +1,176 @@ +package com.mithrilmania.blocktopograph.map.locator; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.World; +import com.mithrilmania.blocktopograph.databinding.FragMapGotoBinding; +import com.mithrilmania.blocktopograph.map.FloatPaneFragment; + +import java.lang.ref.WeakReference; + +public final class AdvancedLocatorFragment extends FloatPaneFragment { + + public static final String PREF_KEY_LOCATOR_PAGE = "locator_page"; + private World mWorld; + private LocatorPageFragment.CameraMoveCallback mCameraMoveCallback; + private LocatorPagerAdapter mAdapter; + + public static AdvancedLocatorFragment create(World world, LocatorPageFragment.CameraMoveCallback cameraMoveCallback) { + AdvancedLocatorFragment ret = new AdvancedLocatorFragment(); + ret.mWorld = world; + ret.mCameraMoveCallback = cameraMoveCallback; + return ret; + } + + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + FragMapGotoBinding binding = DataBindingUtil.inflate(inflater, R.layout.frag_map_goto, container, false); + mAdapter = new LocatorPagerAdapter(getChildFragmentManager(), this); + binding.pager.setAdapter(mAdapter); + binding.header.close.setOnClickListener(view -> { + if (mOnCloseButtonClickListener != null) + mOnCloseButtonClickListener.onCloseButtonClick(); + }); + Activity act = getActivity(); + assert act != null; + int page = act.getPreferences(Context.MODE_PRIVATE).getInt(PREF_KEY_LOCATOR_PAGE, 1); + if (page >= 0 && page < LocatorPagerAdapter.PAGES_COUNT) + binding.pager.setCurrentItem(page); + binding.pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int i, float v, int i1) { + } + + @Override + public void onPageSelected(int i) { + Activity activity = getActivity(); + if (activity == null) return; + activity.getPreferences(Context.MODE_PRIVATE) + .edit() + .putInt(PREF_KEY_LOCATOR_PAGE, i) + .apply(); + mAdapter.doOverScroll(i); + } + + @Override + public void onPageScrollStateChanged(int i) { + } + }); + return binding.getRoot(); + } + + public static class LocatorPagerAdapter extends FragmentPagerAdapter { + + static final int PAGES_COUNT = 3; + + private LocatorPlayersFragment locatorPlayersFragment; + private LocatorMarkersFragment locatorMarkersFragment; + private LocatorCoordFragment locatorCoordFragment; + private WeakReference owner; + + LocatorPagerAdapter(FragmentManager fm, AdvancedLocatorFragment owner) { + super(fm); + this.owner = new WeakReference<>(owner); + } + + @NonNull + private LocatorPlayersFragment getLocatorPlayersFragment( + @NonNull AdvancedLocatorFragment owner) { + if (locatorPlayersFragment == null) { + locatorPlayersFragment = LocatorPlayersFragment.create(owner.mWorld); + locatorPlayersFragment.mCameraMoveCallback = owner.mCameraMoveCallback; + } + return locatorPlayersFragment; + } + + @NonNull + private LocatorMarkersFragment getLocatorMarkersFragment( + @NonNull AdvancedLocatorFragment owner) { + if (locatorMarkersFragment == null) { + locatorMarkersFragment = LocatorMarkersFragment.create(owner.mWorld); + locatorMarkersFragment.mCameraMoveCallback = owner.mCameraMoveCallback; + } + return locatorMarkersFragment; + } + + @NonNull + private LocatorCoordFragment getLocatorCoordFragment( + @NonNull AdvancedLocatorFragment owner) { + if (locatorCoordFragment == null) { + locatorCoordFragment = LocatorCoordFragment.create(); + locatorCoordFragment.mCameraMoveCallback = owner.mCameraMoveCallback; + } + return locatorCoordFragment; + } + + void doOverScroll(int i) { + if (i == 0 && locatorCoordFragment != null) + locatorCoordFragment.doOverScroll(); + } + + @Nullable + @Override + public CharSequence getPageTitle(int position) { + AdvancedLocatorFragment owner = this.owner.get(); + if (owner == null) return null; + switch (position) { + case 1: + return owner.getString(R.string.locator_page_player); + case 2: + return owner.getString(R.string.locator_page_marker); + case 0: + return owner.getString(R.string.locator_page_coor); + default: + return null; + } + } + + @NonNull + private Fragment getAnyPlaceHolderFragment() { + if (locatorPlayersFragment != null) return locatorPlayersFragment; + if (locatorMarkersFragment != null) return locatorMarkersFragment; + if (locatorCoordFragment != null) return locatorCoordFragment; + throw new RuntimeException(); + } + + @Override + @NonNull + public Fragment getItem(int i) { + AdvancedLocatorFragment owner = this.owner.get(); + if (owner == null) { + // Try not trigger a crash. + return getAnyPlaceHolderFragment(); + } + switch (i) { + case 1: + return getLocatorPlayersFragment(owner); + case 2: + return getLocatorMarkersFragment(owner); + case 0: + return getLocatorCoordFragment(owner); + default: + return getAnyPlaceHolderFragment(); + } + } + + @Override + public int getCount() { + return PAGES_COUNT; + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorCoordFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorCoordFragment.java new file mode 100644 index 00000000..450ff6a6 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorCoordFragment.java @@ -0,0 +1,55 @@ +package com.mithrilmania.blocktopograph.map.locator; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.databinding.DataBindingUtil; + +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.databinding.FragLocatorCoordBinding; +import com.mithrilmania.blocktopograph.util.UiUtil; + +public final class LocatorCoordFragment extends LocatorPageFragment { + + private FragLocatorCoordBinding mBinding; + + @NonNull + + public static LocatorCoordFragment create() { + return new LocatorCoordFragment(); + } + + private void onClickGo(View view) { + if (mCameraMoveCallback != null) { + int x, z; + x = UiUtil.readIntFromView(mBinding.editX); + z = UiUtil.readIntFromView(mBinding.editZ); + mCameraMoveCallback.moveCamera(x, z); + } + } + + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate( + inflater, R.layout.frag_locator_coord, container, false); + mBinding.buttonGo.setOnClickListener(this::onClickGo); + mBinding.editZ.setOnEditorActionListener((textView, i, keyEvent) -> { + if (i == 233 && keyEvent != null) { + onClickGo(null); + return true; + } + return false; + }); + return mBinding.getRoot(); + } + + public void doOverScroll() { + mBinding.scroll.doOverScroll(); + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorMarkersFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorMarkersFragment.java new file mode 100644 index 00000000..6795c97d --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorMarkersFragment.java @@ -0,0 +1,170 @@ +package com.mithrilmania.blocktopograph.map.locator; + +import android.app.Activity; +import android.os.AsyncTask; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.World; +import com.mithrilmania.blocktopograph.databinding.FragLocatorPlayersBinding; +import com.mithrilmania.blocktopograph.databinding.ItemLocatorMarkerBinding; +import com.mithrilmania.blocktopograph.map.marker.AbstractMarker; + +import java.lang.ref.WeakReference; +import java.util.Collection; + +public final class LocatorMarkersFragment extends LocatorPageFragment { + + private FragLocatorPlayersBinding mBinding; + private World mWorld; + + public static LocatorMarkersFragment create(World world) { + LocatorMarkersFragment ret = new LocatorMarkersFragment(); + ret.mWorld = world; + return ret; + } + + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate( + inflater, R.layout.frag_locator_players, container, false); + new LoadingTask(this).execute(mWorld); + return mBinding.getRoot(); + } + + private static class MarkersAdapter extends RecyclerView.Adapter { + + @NonNull + private final WeakReference owner; + + @NonNull + private final AbstractMarker[] markers; + + MarkersAdapter(@NonNull WeakReference owner, @NonNull AbstractMarker[] markers) { + this.owner = owner; + this.markers = markers; + } + + @NonNull + @Override + public MeowHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + LocatorPageFragment owner = this.owner.get(); + LayoutInflater inflater; + if (owner != null) inflater = owner.getLayoutInflater(); + else inflater = LayoutInflater.from(viewGroup.getContext()); + + ItemLocatorMarkerBinding binding = DataBindingUtil.inflate( + inflater, R.layout.item_locator_marker, + viewGroup, false + ); + MeowHolder meowHolder = new MeowHolder(binding.getRoot()); + meowHolder.binding = binding; + return meowHolder; + } + + @Override + public void onBindViewHolder(@NonNull MeowHolder meowHolder, int i) { + AbstractMarker marker = markers[i]; + meowHolder.binding.setMarker(marker); + } + + @Override + public int getItemCount() { + return markers.length; + } + + class MeowHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + ItemLocatorMarkerBinding binding; + + MeowHolder(@NonNull View itemView) { + super(itemView); + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + LocatorPageFragment owner = MarkersAdapter.this.owner.get(); + if (owner == null) return; + if (owner.mCameraMoveCallback != null) { + int index = getAdapterPosition(); + AbstractMarker marker = markers[index]; + owner.mCameraMoveCallback.moveCamera(marker.x, marker.z); + } + } + } + + } + + private static class LoadingTask extends AsyncTask { + + private final WeakReference owner; + + private LoadingTask(LocatorMarkersFragment owner) { + this.owner = new WeakReference<>(owner); + } + + @Nullable + @Override + protected AbstractMarker[] doInBackground(World... worlds) { + try { + World world; + if (worlds.length != 1 || (world = worlds[0]) == null) return null; + + Collection markers; + try { + markers = world.getMarkerManager().getMarkers(); + } catch (Exception e) { + Log.d(this, e); + return null; + } + + if (markers == null) return null; + if (markers.isEmpty()) return new AbstractMarker[0]; + try { + return markers.toArray(new AbstractMarker[0]); + } catch (Exception e) { + Log.d(this, e); + return null; + } + + } catch (Exception e) { + Log.d(this, e); + return null; + } + } + + @Override + protected void onPostExecute(AbstractMarker[] markers) { + LocatorMarkersFragment owner = this.owner.get(); + Activity activity; + if (owner == null || (activity = owner.getActivity()) == null) return; + owner.mBinding.loading.setVisibility(View.GONE); + if (markers == null) { + owner.mBinding.empty.setVisibility(View.VISIBLE); + owner.mBinding.empty.setText(R.string.general_failed); + } else if (markers.length == 0) { + owner.mBinding.empty.setVisibility(View.VISIBLE); + owner.mBinding.empty.setText(R.string.no_custom_markers); + } else { + owner.mBinding.list.setLayoutManager( + new LinearLayoutManager(activity)); + owner.mBinding.list.setAdapter( + new MarkersAdapter(new WeakReference<>(owner), markers)); + owner.mBinding.list.setVisibility(View.VISIBLE); + } + } + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorPageFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorPageFragment.java new file mode 100644 index 00000000..7857537d --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorPageFragment.java @@ -0,0 +1,14 @@ +package com.mithrilmania.blocktopograph.map.locator; + +import androidx.fragment.app.Fragment; + +public abstract class LocatorPageFragment extends Fragment { + + protected CameraMoveCallback mCameraMoveCallback; + + public interface CameraMoveCallback { + + void moveCamera(double x, double z); + + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorPlayersFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorPlayersFragment.java new file mode 100644 index 00000000..d7cee04f --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/locator/LocatorPlayersFragment.java @@ -0,0 +1,167 @@ +package com.mithrilmania.blocktopograph.map.locator; + +import android.os.AsyncTask; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.databinding.DataBindingUtil; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.World; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.databinding.FragLocatorPlayersBinding; +import com.mithrilmania.blocktopograph.databinding.ItemLocatorPlayerBinding; +import com.mithrilmania.blocktopograph.map.Player; +import com.mithrilmania.blocktopograph.util.math.DimensionVector3; + +import java.lang.ref.WeakReference; + +public final class LocatorPlayersFragment extends LocatorPageFragment { + + private FragLocatorPlayersBinding mBinding; + private World mWorld; + + public static LocatorPlayersFragment create(World world) { + LocatorPlayersFragment ret = new LocatorPlayersFragment(); + ret.mWorld = world; + return ret; + } + + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate( + inflater, R.layout.frag_locator_players, container, false); + new LoadingTask(this).execute(mWorld); + return mBinding.getRoot(); + } + + private static class PlayersAdapter extends RecyclerView.Adapter { + + private final WeakReference owner; + private final Player[] players; + + PlayersAdapter(WeakReference owner, Player[] players) { + this.owner = owner; + this.players = players; + } + + @NonNull + @Override + public MeowHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + LocatorPageFragment owner = this.owner.get(); + assert owner != null; + ItemLocatorPlayerBinding binding = DataBindingUtil.inflate( + owner.getLayoutInflater(), R.layout.item_locator_player, + viewGroup, false + ); + MeowHolder meowHolder = new MeowHolder(binding.getRoot()); + meowHolder.binding = binding; + return meowHolder; + } + + @Override + public void onBindViewHolder(@NonNull MeowHolder meowHolder, int i) { + Player player = players[i]; + meowHolder.binding.setPlayer(player); + } + + @Override + public int getItemCount() { + return players.length; + } + + class MeowHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + ItemLocatorPlayerBinding binding; + + MeowHolder(@NonNull View itemView) { + super(itemView); + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + LocatorPageFragment owner = PlayersAdapter.this.owner.get(); + if (owner == null) return; + if (owner.mCameraMoveCallback != null) { + int index = getAdapterPosition(); + DimensionVector3 pos = players[index].getPosition(); + if (pos != null) + owner.mCameraMoveCallback.moveCamera(pos.x, pos.z); + } + } + } + + } + + private static class LoadingTask extends AsyncTask { + + private final WeakReference owner; + + private LoadingTask(LocatorPlayersFragment owner) { + this.owner = new WeakReference<>(owner); + } + + @Override + protected Player[] doInBackground(World... worlds) { + World world; + if (worlds.length != 1 || (world = worlds[0]) == null) return null; + WorldData worldData = world.getWorldData(); + try { + worldData.openDB(); + DimensionVector3 localPlayerPos = world.getPlayerPos(); + String[] mlst = worldData.getNetworkPlayerNames(); + Player[] players; + int offset; + if (localPlayerPos == null) { + players = new Player[mlst.length]; + offset = 0; + } else { + players = new Player[mlst.length + 1]; + offset = 1; + players[0] = Player.localPlayer(); + players[0].setPosition(localPlayerPos); + } + for (int i = 0; i < mlst.length; i++) { + Player player = Player.networkPlayer(mlst[i]); + try { + player.setPosition(world.getMultiPlayerPos(mlst[i])); + } catch (Exception e) { + Log.d(this, e); + } + players[i + offset] = player; + } + return players; + } catch (Exception e) { + Log.d(this, e); + return null; + } + } + + @Override + protected void onPostExecute(Player[] players) { + LocatorPlayersFragment owner = this.owner.get(); + if (owner == null) return; + owner.mBinding.loading.setVisibility(View.GONE); + if (players == null || players.length == 0) { + owner.mBinding.empty.setVisibility(View.VISIBLE); + owner.mBinding.empty.setText(R.string.failed_find_player); + } else { + owner.mBinding.list.setLayoutManager( + new LinearLayoutManager(owner.getActivity())); + owner.mBinding.list.setAdapter( + new PlayersAdapter(new WeakReference<>(owner), players)); + owner.mBinding.list.setVisibility(View.VISIBLE); + } + } + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/AbstractMarker.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/AbstractMarker.java index cde65996..fb1ce417 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/AbstractMarker.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/AbstractMarker.java @@ -1,9 +1,10 @@ package com.mithrilmania.blocktopograph.map.marker; import android.content.Context; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.widget.ImageView; +import com.mithrilmania.blocktopograph.R; import com.mithrilmania.blocktopograph.map.Dimension; import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; import com.mithrilmania.blocktopograph.util.NamedBitmapProviderHandle; @@ -27,25 +28,33 @@ public AbstractMarker(int x, int y, int z, Dimension dimension, NamedBitmapProvi this.isCustom = isCustom; } - public int getChunkX(){ + public String getPositionDescription(Context context) { + return context.getString(R.string.player_position_desc, + Math.round(x), Math.round(y), + Math.round(z), context.getString(dimension.getName())); + } + + public int getChunkX() { return x >> 4; } - public int getChunkZ(){ + public int getChunkZ() { return z >> 4; } public MarkerImageView view; public MarkerImageView getView(Context context) { - if(view != null) return view; - view = new MarkerImageView(context, this); - this.loadIcon(view); + if (view == null) { + view = new MarkerImageView(context, this); + this.loadIcon(view); + } return view; } /** * Loads the provided bitmap into the image view. + * * @param iconView The view to load the icon into. */ public void loadIcon(ImageView iconView) { @@ -70,10 +79,10 @@ public boolean equals(Object o) { AbstractMarker that = (AbstractMarker) o; return x == that.x - && y == that.y - && z == that.z - && dimension == that.dimension - && (namedBitmapProvider != null + && y == that.y + && z == that.z + && dimension == that.dimension + && (namedBitmapProvider != null ? namedBitmapProvider.equals(that.namedBitmapProvider) : that.namedBitmapProvider == null); diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/CustomNamedBitmapProvider.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/CustomNamedBitmapProvider.java index 4a517cd0..452d9e18 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/CustomNamedBitmapProvider.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/CustomNamedBitmapProvider.java @@ -2,7 +2,7 @@ import android.graphics.Bitmap; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.mithrilmania.blocktopograph.util.NamedBitmapProvider; diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/MarkerImageView.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/MarkerImageView.java index 49000ed7..4530cd40 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/MarkerImageView.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/marker/MarkerImageView.java @@ -6,7 +6,7 @@ /** * TODO docs */ -public class MarkerImageView extends android.support.v7.widget.AppCompatImageView { +public class MarkerImageView extends androidx.appcompat.widget.AppCompatImageView { private final AbstractMarker markerHook; diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/AnalyzeTask.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/AnalyzeTask.java new file mode 100644 index 00000000..bc6f8aa2 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/AnalyzeTask.java @@ -0,0 +1,219 @@ +package com.mithrilmania.blocktopograph.map.picer; + +import android.app.Activity; +import android.graphics.Rect; +import android.os.AsyncTask; + +import com.litl.leveldb.DB; +import com.litl.leveldb.Iterator; +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.World; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Version; +import com.mithrilmania.blocktopograph.map.Dimension; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.AlertDialog; + +class AnalyzeTask extends AsyncTask { + + private final WeakReference owner; + private boolean hasWrongChunks; + private boolean hasOldChunks; + private AlertDialog waitDialog; + + AnalyzeTask(PicerFragment owner) { + this.owner = new WeakReference<>(owner); + } + + @Override + protected void onPreExecute() { + PicerFragment owner = this.owner.get(); + Activity activity; + if (owner == null || (activity = owner.getActivity()) == null) { + cancel(true); + return; + } + waitDialog = UiUtil.buildProgressWaitDialog(activity, R.string.picer_progress_analyzing, + dialogInterface -> { + PicerFragment diaFrag = AnalyzeTask.this.owner.get(); + if (diaFrag != null) diaFrag.dismiss(); + }); + waitDialog.show(); + } + + @Override + @Nullable + protected Rect doInBackground(Void... voids) { + + PicerFragment owner = this.owner.get(); + if (owner == null) return null; + + // Get db. + DB db = null; + getDb: + { + World world = owner.mWorld; + if (world == null) break getDb; + WorldData worldData = world.getWorldData(); + try { + worldData.openDB(); + } catch (Exception e) { + break getDb; + } + db = worldData.db; + } + if (db == null) return null; + + Dimension dimension = owner.mDimension; + int verKeyLenOfDim; + switch (dimension) { + case OVERWORLD: + verKeyLenOfDim = 9; + break; + case NETHER: + case END: + verKeyLenOfDim = 13; + break; + default: + return null; + } + + // We used to separate world into areas or clusters, now that + // we have selection so just measure whole world here. + // If it's too large we just say select before using this. + //List areas = new ArrayList<>(32); + //Area.maxDist = 10; + Rect rect = null; + + // Iterate over all items. + try { + db.put(new byte[]{0, 1, 2, 3, 0, 1, 2, 3, 118}, new byte[]{0}); + Iterator iterator = db.iterator(); + boolean cancelled = false; + int loopCount = 0; + loop: + for (iterator.seekToFirst(); iterator.isValid(); iterator.next(), loopCount++) { + + if (isCancelled()) { + cancelled = true; + break; + } + + // Is it a key for a chunk of current dim's version record? + byte[] key = iterator.getKey(); + if (key.length != verKeyLenOfDim) continue; + if (key[verKeyLenOfDim - 1] != (byte) 0x76) continue; + ByteBuffer byteBuffer = ByteBuffer.wrap(key); + byteBuffer.order(ByteOrder.LITTLE_ENDIAN); + int x = byteBuffer.getInt(); + int z = byteBuffer.getInt(); + // Wrong dim. + if (verKeyLenOfDim == 13 && dimension.id != byteBuffer.getInt()) continue; + byte[] value = iterator.getValue(); + Version version = Version.getVersion(value); + // Record unsupported stuff and skip. + switch (version) { + case ERROR: + case NULL: + hasWrongChunks = true; + continue loop; + case OLD_LIMITED: + hasOldChunks = true; + continue loop; + } + + if (rect != null) { + if (x < rect.left) rect.left = x; + else if (x > rect.right) rect.right = x; + if (z < rect.top) rect.top = z; + else if (z > rect.bottom) rect.bottom = z; + if (rect.right - rect.left > PicerFragment.MAX_LENGTH + || rect.bottom - rect.top > PicerFragment.MAX_LENGTH + || loopCount % 36 == 0 && (rect.right - rect.left) * (rect.bottom - rect.top) > PicerFragment.MAX_AREA) + break; + } else { + rect = new Rect(x, z, x, z); + } + + // Add the chunk to area list. +// add: +// { +// for (Area area : areas) { +// // Try add to existing areas. +// if (area.add(x, z)) break add; +// } +// // Failed then create new. +// areas.add(new Area(x, z)); +// } +// // As more chunks were read maybe we can merge more of them. +// if (loopCount > 16) Area.absMergeList(areas); + } + iterator.close(); + if (cancelled) return null; + } catch (Throwable e) { + Log.d(this, e); + return null; + } + + // Final merge. Redundant? Who cares. +// Area.absMergeList(areas); +// +// owner = this.owner.get(); +// if (owner == null) return null; +// +// if (areas.size() == 0) return null; +// if (areas.size() == 1) return areas.get(0); +// +// // Then should decide which area to use based on camera position. +// // For not let's ignore. +// return areas.get(0); + if (rect != null) { + rect.left *= 16; + rect.top *= 16; + rect.right *= 16 + 15; + rect.bottom *= 16 + 15; + } + return rect; + } + + @Override + protected void onCancelled() { + PicerFragment owner = this.owner.get(); + if (owner != null) { + owner.mOngoingTask = null; + waitDialog.dismiss(); + } + } + + @Override + protected void onPostExecute(@Nullable Rect rect) { + + // We finished too late. No longer needed. + PicerFragment owner = this.owner.get(); + if (owner == null) return; + owner.mOngoingTask = null; + waitDialog.dismiss(); + + if (rect != null) { + owner.onAnalyzeDone(rect); + + } else if (hasWrongChunks || hasOldChunks) { + // Size 0 with exception, dismiss and show exception in dialog. + @StringRes int strId; + if (hasWrongChunks) strId = R.string.picer_failed_corrupt; + else strId = R.string.picer_failed_old; + owner.showFailureDialogAndDismiss(strId); + + // Otherwise a toast is enough. + } else owner.showFailureMsgAndDismiss(R.string.picer_failed_nodata); + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/Area.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/Area.java new file mode 100644 index 00000000..0545c289 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/Area.java @@ -0,0 +1,96 @@ +package com.mithrilmania.blocktopograph.map.picer; + +import java.util.ArrayList; +import java.util.List; + +import androidx.annotation.NonNull; + +public class Area { + + static int maxDist; + + int mMinX; + int mMinZ; + int mMaxX; + int mMaxZ; + private final List mList; + + Area(int firstX, int firstZ) { + mMaxX = mMinX = firstX; + mMaxZ = mMinZ = firstZ; + mList = new ArrayList<>(16); + } + + boolean add(int x, int z) { + if (x >= mMinX - maxDist && x <= mMaxX + maxDist + && z >= mMinZ - maxDist && z <= mMaxZ + maxDist) { + if (x < mMinX) mMinX = x; + else if (x > mMaxX) mMaxX = x; + if (z < mMinZ) mMinZ = z; + else if (z > mMaxZ) mMaxZ = z; + mList.add(new Member(x, z)); + return true; + } + return false; + } + + private boolean absMerge(@NonNull Area another) { + if (another.mMaxX >= mMinX - maxDist && another.mMinX <= mMaxX + maxDist + && another.mMaxZ >= mMinZ - maxDist && another.mMinZ <= mMaxZ + maxDist) { + if (another.mMinX < mMinX) mMinX = another.mMinX; + else if (another.mMaxX > mMaxX) mMaxX = another.mMaxX; + if (another.mMinZ < mMinZ) mMinZ = another.mMinZ; + else if (another.mMaxZ > mMaxZ) mMaxZ = another.mMaxZ; + mList.addAll(another.mList); + return true; + } + return false; + } + + static void absMergeList(@NonNull List list) { + boolean hasOp; + do { + hasOp = false; + for (int i = list.size() - 1; i > 0; i--) { + Area toBeMerged = list.get(i); + assert toBeMerged != null; + for (int j = 0; j < i; j++) { + if (list.get(j).absMerge(toBeMerged)) { + list.remove(toBeMerged); + hasOp = true; + break; + } + } + } + } while (hasOp); + } + + @NonNull + List getList() { + return mList; + } + + int calculateArea() { + return (mMaxX - mMinX) * (mMaxZ - mMinZ); + } + + public int width() { + return mMaxX - mMinX; + } + + public int height() { + return mMaxZ - mMinZ; + } + + class Member { + + public int x; + public int z; + + Member(int x, int z) { + this.x = x; + this.z = z; + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/GenerateThread.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/GenerateThread.java new file mode 100644 index 00000000..efbf24e7 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/GenerateThread.java @@ -0,0 +1,113 @@ +package com.mithrilmania.blocktopograph.map.picer; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.FragmentActivity; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.map.Dimension; +import com.mithrilmania.blocktopograph.map.edit.RectEditTarget; +import com.mithrilmania.blocktopograph.map.renderer.MapRenderer; + +import java.lang.ref.WeakReference; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +class GenerateThread extends Thread { + + private final Rect area; + private final WeakReference owner; + private final int scale; + private final Bitmap.Config config; + private final WeakReference dialog; + + private boolean cancelled; + + GenerateThread(PicerFragment owner, Rect area, int scale, Bitmap.Config config, + AlertDialog dialog) { + this.owner = new WeakReference<>(owner); + this.area = area; + this.scale = scale; + this.config = config; + this.dialog = new WeakReference<>(dialog); + } + + @Override + public void run() { + + PicerFragment owner = this.owner.get(); + if (owner == null) return; + + Dimension dimension = owner.mDimension; + MapRenderer renderer = dimension.defaultMapType.renderer; + WorldData wdata = owner.mWorld.getWorldData(); + + int width = area.right - area.left + 1; + int height = area.bottom - area.top + 1; + + Bitmap bitmap = Bitmap.createBitmap(width * scale, height * scale, config); + Canvas canvas = new Canvas(bitmap); + + int poolSize = 5; + + ExecutorService executor = + new ThreadPoolExecutor(poolSize, poolSize, 0, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(poolSize << 1), + new ThreadPoolExecutor.CallerRunsPolicy()); + + ThreadLocal paintSub = new ThreadLocal() { + @NonNull + @Override + protected Paint initialValue() { + return new Paint(); + } + }; + + new RectEditTarget(wdata, area, dimension).forEachChunk( + (chunk, fromX, toX, fromY, toY, fromZ, toZ) -> { + if (cancelled) { + executor.shutdownNow(); + return 0; + } + executor.execute(() -> { + try { + renderer.renderToBitmap(chunk, canvas, dimension, chunk.mChunkX, chunk.mChunkZ, + (chunk.mChunkX * 16 - area.left) * scale, + (chunk.mChunkZ * 16 - area.top) * scale, + scale, scale, paintSub.get(), wdata); + } catch (Exception e) { + Log.d(this, e); + } + }); + return 0; + }); + executor.shutdown(); + try { + executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + return; + } + + owner = this.owner.get(); + if (owner == null) return; + + FragmentActivity activity = owner.getActivity(); + if (activity != null) + activity.runOnUiThread(() -> this.owner.get().onGenerationDone(bitmap, dialog.get())); + + owner.mOngoingThread = null; + } + + void cancel() { + cancelled = true; + interrupt(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/PicerFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/PicerFragment.java new file mode 100644 index 00000000..808d97e9 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/PicerFragment.java @@ -0,0 +1,336 @@ +package com.mithrilmania.blocktopograph.map.picer; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.media.MediaScannerConnection; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ScrollView; +import android.widget.SeekBar; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.annotation.UiThread; +import androidx.appcompat.app.AlertDialog; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.DialogFragment; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.google.android.material.snackbar.Snackbar; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.World; +import com.mithrilmania.blocktopograph.databinding.FragPicerBinding; +import com.mithrilmania.blocktopograph.map.Dimension; +import com.mithrilmania.blocktopograph.map.OpenLongPressMenuHandler; +import com.mithrilmania.blocktopograph.util.ConvertUtil; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.io.File; + +public final class PicerFragment extends DialogFragment { + + public static final int MAX_LENGTH = 2048; + public static final int MAX_AREA = 64 * 64 * 256; + public static final int MAX_SCALE = 32; + private FragPicerBinding mBinding; + Rect mRange; + + World mWorld; + Dimension mDimension; + AsyncTask mOngoingTask; + private int stage = 0; + GenerateThread mOngoingThread; + private OpenLongPressMenuHandler mOpenLongPressMenuHandler; + + public static PicerFragment create(@NonNull World world, @NonNull Dimension dimension, + @Nullable Rect range, @Nullable OpenLongPressMenuHandler openLongPressMenuHandler) { + PicerFragment ret = new PicerFragment(); + ret.mWorld = world; + ret.mDimension = dimension; + ret.mRange = range; + ret.mOpenLongPressMenuHandler = openLongPressMenuHandler; + return ret; + } + + private static boolean rangeCheck(@NonNull Rect rect) { + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + return width <= MAX_LENGTH && height <= MAX_LENGTH && width * height <= MAX_AREA; + } + + @NonNull + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate(inflater, R.layout.frag_picer, + container, false); + mBinding.finalButton.setOnClickListener(this::onClickFinalButton); + mBinding.scaleSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int i, boolean b) { + mBinding.setScale(i + 1); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + View root = mBinding.getRoot(); + Dialog dialog = getDialog(); + if (dialog instanceof AlertDialog) + ((AlertDialog) dialog).setView(root); + if (mRange == null) + root.post(() -> mOngoingTask = new AnalyzeTask(this).execute()); + else goToScalePhase(); + return root; + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(requireContext(), R.style.AppTheme_Dialog)) + .setTitle(R.string.picer_title) + .create(); + dialog.setCanceledOnTouchOutside(false); + return dialog; + } + + @Override + public void onDismiss(@NonNull DialogInterface dialog) { + super.onDismiss(dialog); + if (mOngoingTask != null) mOngoingTask.cancel(true); + if (mOngoingThread != null) mOngoingThread.cancel(); + } + + // Result callbacks from AnalyzeTask. + + @UiThread + void showFailureDialogAndDismiss(@StringRes int resId) { + Activity activity = getActivity(); + if (activity == null) return; + AlertDialog dialog = new AlertDialog.Builder(activity) + .setMessage(resId) + .create(); + dialog.show(); + dismiss(); + } + + @UiThread + void showFailureMsgAndDismiss(@StringRes int resId) { + Activity activity = getActivity(); + if (activity == null) return; + Toast.makeText(activity, resId, Toast.LENGTH_SHORT).show(); + dismiss(); + } + + private void goToScalePhase() { + Activity activity = getActivity(); + if (activity == null) return; + mBinding.selectCase.setVisibility(View.VISIBLE); + int w = mRange.right - mRange.left; + int h = mRange.bottom - mRange.top; + if (w <= 0 || h <= 0) { + dismiss(); + return; + } + int len = w > h ? w : h; + int maxScale = MAX_LENGTH / len; + len = w * h; + w = MAX_AREA / len; + if (w < maxScale) maxScale = w; + if (maxScale <= 0) { + new AlertDialog.Builder(activity) + .setTitle(R.string.map_picer_selection_too_large) + .setMessage(getString(R.string.map_picer_selection_too_large_detail, MAX_LENGTH, MAX_AREA)) + .setPositiveButton(android.R.string.ok, null) + .create() + .show(); + dismiss(); + return; + } else if (maxScale == 1) { + mBinding.scaleBox.setVisibility(View.GONE); + mBinding.scaleNot.setVisibility(View.VISIBLE); + } else { + if (MAX_SCALE < maxScale) maxScale = MAX_SCALE; + mBinding.scaleBox.setVisibility(View.VISIBLE); + mBinding.scaleNot.setVisibility(View.GONE); + mBinding.scaleSeek.setMax(maxScale - 1); + mBinding.scaleSeek.setProgress(maxScale - 1); + } + stage = 1; + mBinding.finalButton.setVisibility(View.VISIBLE); + mBinding.finalButton.setText(R.string.picer_btn_generate); +// Minimal 16x16 px per chunk. +// int size = area.calculateArea() * 256; +// +// // Oops. +// if (size > MAX_PIXELS) { +// showFailureDialogAndDismiss(R.string.picer_failed_too_large); +// return; +// } +// +// // How many levels could we scale. +// int levels = 1; +// for (int m = size; m <= MAX_PIXELS / 2; levels++) m *= 4; +// +// if (levels == 1) { +// // Cannot scale at all. +// mBinding.scaleBox.setVisibility(View.GONE); +// mBinding.scaleNot.setVisibility(View.VISIBLE); +// mBinding.scaleSeek.setMax(1); +// mBinding.scaleSeek.setProgress(1); +// } else { +// mBinding.scaleSeek.setMax(levels - 1); +// mBinding.scaleSeek.setProgress(levels - 1); +// } +// mBinding.selectCase.setVisibility(View.VISIBLE); +// mBinding.setArea(area); +// +// mBinding.finalButton.setVisibility(View.VISIBLE); +// mBinding.finalButton.setText(R.string.picer_btn_generate); + } + + @UiThread + private void onClickFinalButton(@NonNull View view) { + switch (stage) { + case 1: + onClickGenerate(); + break; + case 2: + onClickSave(view); + break; + } + } + + @UiThread + void onAnalyzeDone(@NonNull Rect rect) { + + Activity activity = getActivity(); + if (activity == null) return; + + if (rangeCheck(rect)) { + mRange = rect; + goToScalePhase(); + } else { + new AlertDialog.Builder(activity) + .setTitle(R.string.map_picer_world_too_large) + .setMessage(R.string.map_picer_use_selection_instead) + .setPositiveButton(android.R.string.ok, (dia, i) -> mOpenLongPressMenuHandler.open()) + .create().show(); + dismiss(); + } + } + + // Callback from . + + @UiThread + private void onClickGenerate() { + Activity activity = getActivity(); + if (activity == null) return; + + int scale = mBinding.scaleSeek.getProgress() + 1; + AlertDialog dialog = UiUtil.buildProgressWaitDialog( + activity, R.string.picer_progress_generating, dialogInterface -> dismiss()); + dialog.show(); + + mBinding.finalButton.setVisibility(View.GONE); + mBinding.selectCase.setVisibility(View.GONE); + + mOngoingThread = new GenerateThread(this, mRange, scale, Bitmap.Config.ARGB_8888, dialog); + mOngoingThread.start(); + } + + @UiThread + void onGenerationDone(@Nullable Bitmap bitmap, @Nullable AlertDialog dialog) { + + if (dialog != null) dialog.dismiss(); + + if (bitmap == null) { + Activity activity = getActivity(); + if (activity != null) Toast.makeText( + activity, R.string.general_failed, Toast.LENGTH_SHORT).show(); + dismiss(); + return; + } + + stage = 2; + mBinding.finalButton.setVisibility(View.VISIBLE); + mBinding.finalButton.setText(R.string.picer_save); + mBinding.finalButton.setTag(bitmap); + mBinding.previewCase.setVisibility(View.VISIBLE); + + Glide.with(this).load(bitmap).listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + // How could. + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + mBinding.scroll.post(() -> + mBinding.scroll.fullScroll(ScrollView.FOCUS_DOWN)); + return false; + } + }).into(mBinding.image); + + } + + @UiThread + private void onClickSave(@NonNull View view) { + Object o = view.getTag(); + if (!(o instanceof Bitmap)) return; + Bitmap bmp = (Bitmap) o; + view.setTag(null); + String name = mWorld.getWorldDisplayName(); + name = ConvertUtil.getLegalFileName(name); + new SaveTask(this, name).execute(bmp); + } + + @UiThread + void onSavedBitmap(@Nullable File file) { + Activity activity = getActivity(); + if (activity == null) return; + if (file == null) + Toast.makeText(activity, R.string.general_failed, Toast.LENGTH_SHORT).show(); + else { + MediaScannerConnection.scanFile(activity, + new String[]{file.getAbsolutePath()}, + new String[]{"image/png"}, null); + Snackbar snackbar = Snackbar.make( + activity.getWindow().getDecorView(), + getString(R.string.picer_saved), Snackbar.LENGTH_SHORT) + .setAction(R.string.general_share, v -> { + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file)); + shareIntent.setType("image/jpeg"); + getActivity().startActivity( + Intent.createChooser(shareIntent, + v.getContext().getString(R.string.picer_share_title))); + }); + snackbar.show(); + dismiss(); + } + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/PreviewGenerateThread.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/PreviewGenerateThread.java new file mode 100644 index 00000000..825d0979 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/PreviewGenerateThread.java @@ -0,0 +1,60 @@ +package com.mithrilmania.blocktopograph.map.picer; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.os.AsyncTask; +import android.util.Pair; + +import java.lang.ref.WeakReference; + +public class PreviewGenerateThread extends AsyncTask, Void> { + + private int MAX_DIM = 800; + private final WeakReference owner; + + PreviewGenerateThread(PicerFragment owner) { + this.owner = new WeakReference<>(owner); + } + + @Override + protected Void doInBackground(Area... areas) { + assert areas != null; + for (int i = 0; i < areas.length; i++) { + Bitmap bitmap = null; + flow: + { + Area area = areas[i]; + int width = area.width(); + int height = area.height(); + // Wow man that's way too large! 'll be broken~ + // ( What the hell are you thinking about ) + if (width > MAX_DIM || height > MAX_DIM) break flow; + // Scale up unless reach limit. + int scale = MAX_DIM / Math.max(width, height); + bitmap = Bitmap.createBitmap( + width * scale, height * scale, Bitmap.Config.ALPHA_8); + Canvas canvas = new Canvas(bitmap); + Paint paint = new Paint(); + paint.setAlpha(127); + for (Area.Member mem : area.getList()) { + int x = mem.x - area.mMinX; + int y = mem.z - area.mMinZ; + canvas.drawRect(new Rect( + x * scale, y * scale, + (x + 1) * scale, (y + 1) * scale), paint); + } + } + //noinspection unchecked + publishProgress(new Pair<>(i, bitmap)); + } + return null; + } + + @SafeVarargs + @Override + protected final void onProgressUpdate(Pair... values) { + // + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/SaveTask.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/SaveTask.java new file mode 100644 index 00000000..ac1851d4 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/picer/SaveTask.java @@ -0,0 +1,62 @@ +package com.mithrilmania.blocktopograph.map.picer; + + +import android.app.Activity; +import android.graphics.Bitmap; +import android.os.AsyncTask; +import android.os.Environment; + +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.util.IoUtil; + +import java.io.File; +import java.lang.ref.WeakReference; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; + +class SaveTask extends AsyncTask { + + private final WeakReference owner; + private WeakReference dialog; + private final String worldName; + + SaveTask(PicerFragment owner, String worldName) { + this.owner = new WeakReference<>(owner); + this.worldName = worldName; + } + + @Override + protected void onPreExecute() { + PicerFragment owner = this.owner.get(); + if (owner == null) return; + Activity activity = owner.getActivity(); + if (activity == null) return; + AlertDialog dia = new AlertDialog.Builder(activity) + .setView(R.layout.general_wait) + .setCancelable(false) + .create(); + dia.setCanceledOnTouchOutside(false); + dia.show(); + dialog = new WeakReference<>(dia); + } + + @Override + protected File doInBackground(Bitmap... bitmaps) { + // assert bitmaps != null && bitmaps.length == 1; + Bitmap bmp = bitmaps[0]; + assert bmp != null; + return IoUtil.saveBitmap(bmp, Bitmap.CompressFormat.PNG, 0, + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + worldName + "_map", true); + } + + @Override + protected void onPostExecute(@Nullable File result) { + AlertDialog dia; + if (dialog != null && (dia = dialog.get()) != null) dia.dismiss(); + PicerFragment owner = this.owner.get(); + if (owner == null) return; + owner.onSavedBitmap(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BiomeRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BiomeRenderer.java index 1c93d71e..9b6f4e0b 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BiomeRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BiomeRenderer.java @@ -1,73 +1,37 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import com.mithrilmania.blocktopograph.WorldData; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; import com.mithrilmania.blocktopograph.map.Biome; import com.mithrilmania.blocktopograph.map.Dimension; - public class BiomeRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); - - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - //the bottom sub-chunk is sufficient to get biome data. - TerrainChunkData data = chunk.getTerrain((byte) 0); - if(data == null || !data.load2DData()) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { int x, z, biomeID, color, i, j, tX, tY; Biome biome; - for (z = bZ, tY = pY ; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { - + for (z = 0, tY = pY; z < 16; z++, tY += pL) { + for (x = 0, tX = pX; x < 16; x++, tX += pW) { - biomeID = data.getBiome(x, z) & 0xff; + biomeID = chunk.getBiome(x, z) & 0xff; biome = Biome.getBiome(biomeID); color = biome == null ? 0xff000000 : (biome.color.red << 16) | (biome.color.green << 8) | (biome.color.blue) | 0xff000000; - for(i = 0; i < pL; i++){ - for(j = 0; j < pW; j++){ - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - - return bm; } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BlockLightRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BlockLightRenderer.java index bc12c772..bf9bc79b 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BlockLightRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/BlockLightRenderer.java @@ -1,86 +1,50 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import com.mithrilmania.blocktopograph.WorldData; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; import com.mithrilmania.blocktopograph.map.Dimension; - public class BlockLightRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); - - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - - int x, y, z, subChunk, color, i, j, tX, tY; + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { + + int x, y, z, subChunk, color, yLim, tX, tY; //render width in blocks - int rW = eX - bX; - int[] light = new int[rW * (eZ - bZ)]; - - for(subChunk = 0; subChunk < cVersion.subChunks; subChunk++) { - TerrainChunkData data = chunk.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()) break; - - for (z = bZ; z < eZ; z++) { - for (x = bX; x < eX; x++) { - for (y = 0; y < cVersion.subChunkHeight; y++) { - light[((z - bZ) * rW) + (x - bX)] += data.getBlockLightValue(x, y, z) & 0xff; - } + int rW = 16; + int[] light = new int[rW * 16]; + + yLim = chunk.getHeightLimit(); + + for (z = 0; z < 16; z++) { + for (x = 0; x < 16; x++) { + for (y = 0; y < yLim; y++) { + light[(z * rW) + x] += chunk.getBlockLightValue(x, y, z) & 0xff; } } } int l; - for (z = bZ, tY = pY; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { + for (z = 0, tY = pY; z < 16; z++, tY += pL) { + for (x = 0, tX = pX; x < 16; x++, tX += pW) { - l = light[((z - bZ) * rW) + (x - bX)]; + l = light[(z * rW) + x]; l = l < 0 ? 0 : ((l > 0xff) ? 0xff : l); color = (l << 16) | (l << 8) | (l) | 0xff000000; - for(i = 0; i < pL; i++){ - for(j = 0; j < pW; j++){ - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - - if(subChunk == 0) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - return bm; } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/CaveRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/CaveRenderer.java index 7aa2beae..ffd7d1c1 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/CaveRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/CaveRenderer.java @@ -1,70 +1,34 @@ package com.mithrilmania.blocktopograph.map.renderer; - -import android.graphics.Bitmap; - +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.OldBlock; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; -import com.mithrilmania.blocktopograph.map.Block; import com.mithrilmania.blocktopograph.map.Dimension; - public class CaveRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); - - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { boolean solid, intoSurface; - int id, meta, cavyness, layers, offset; - Block block; - int x, y, z, subChunk, color, i, j, tX, tY, r, g, b; - - //the bottom sub-chunk is sufficient to get heightmap data. - TerrainChunkData floorData = chunk.getTerrain((byte) 0); - if(floorData == null || !floorData.load2DData()) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); + int cavyness, layers; - TerrainChunkData data; - - for (z = bZ, tY = pY; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { + for (int z = 0, tY = pY; z < 16; z++, tY += pL) { + for (int x = 0, tX = pX; x < 16; x++, tX += pW) { solid = false; intoSurface = false; cavyness = 0; layers = 0; - y = floorData.getHeightMapValue(x, z); - offset = y % cVersion.subChunkHeight; - subChunk = y / cVersion.subChunkHeight; - /* while (cavefloor > 0) { caveceil = chunk.getCaveYUnderAt(x, z, cavefloor - 1); @@ -78,104 +42,78 @@ public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, in */ - r = g = b = 0; - - subChunkLoop: for(; subChunk >= 0; subChunk--) { - - data = chunk.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()){ - //start at the top of the next chunk! (current offset might differ) - offset = cVersion.subChunkHeight - 1; - continue; - } - - - for (y = offset; y >= 0; y--) { - - id = data.getBlockTypeId(x, y, z) & 0xff; - - meta = data.getBlockData(x, y, z) & 0xff; - block = Block.getBlock(id, meta); - - //try the default meta value: 0 - if (block == null) block = Block.getBlock(id, 0); - - switch (id) { - case 0: - //count the number of times it goes from solid to air - if(solid) layers++; - - //count the air blocks underground, - // but avoid trees by skipping the first layer - if(intoSurface) cavyness++; - break; - case 66://rail - if (b < 150) { - b = 150; - r = g = 50; - } - break; - case 5://wooden plank - if (b < 100) { - b = 100; - r = g = 100; - } - break; - case 52://monster spawner - r = g = b = 255; - break subChunkLoop; - case 54://chest - if (b < 170) { - b = 170; - r = 240; - g = 40; - } - break; - case 98://stone bricks - if (b < 145) { - b = 145; - r = g = 120; - } - break; - case 48://moss cobblestone - case 4://cobblestone - if (b < 140) { - b = 140; - r = g = 100; - } - break; + int r = 0, g = 0, b = 0; + + for (int y = chunk.getHeightMapValue(x, z); y >= 0; y--) { + + var blockTemplate = chunk.getBlockTemplate(x, y, z, 0); + + //wooden plank + //stone bricks + //moss cobblestone + if (BlockTemplates.getAirTemplate().equals(blockTemplate)) { + //count the number of times it goes from solid to air + if (solid) layers++; + //count the air blocks underground, + // but avoid trees by skipping the first layer + if (intoSurface) cavyness++; + } else { + var blockName = blockTemplate.getBlock().getName(); + if ("minecraft:rail".equals(blockName)) {//rail + if (b < 150) { + b = 150; + r = g = 50; + } + } else if ("minecraft:planks".equals(blockName)) { + if (b < 100) { + b = 100; + r = g = 100; + } + } else if ("minecraft:mob_spawner".equals(blockName)) {//monster spawner + r = g = b = 255; + break; + } else if ("minecraft:chest".equals(blockName)) {//chest + if (b < 170) { + b = 170; + r = 240; + g = 40; + } + } else if ("minecraft:stonebrick".equals(blockName)) { + if (b < 145) { + b = 145; + r = g = 120; + } + } else if ("minecraft:mossy_cobblestone".equals(blockName) || "minecraft:cobblestone".equals(blockName)) {//cobblestone + if (b < 140) { + b = 140; + r = g = 100; + } } - r += data.getBlockLightValue(x, y, z); - solid = block != null && block.color.alpha == 0xff; - intoSurface |= solid && (y < 60 || layers > 0); } + r += chunk.getBlockLightValue(x, y, z); + solid = Color.alpha(blockTemplate.getColor()) == 0xff; + intoSurface |= solid && (y < 60 || layers > 0); } - if (g == 0 && layers > 0){ + if (g == 0 && layers > 0) { g = (r + 2) * cavyness; r *= 32 * layers; b = 16 * cavyness * (layers - 1); } else r *= r; - r = r < 0 ? 0 : r > 255 ? 255 : r; - g = g < 0 ? 0 : g > 255 ? 255 : g; + r = r < 0 ? 0 : Math.min(r, 255); + g = g < 0 ? 0 : Math.min(g, 255); //b = b < 0 ? 0 : b > 255 ? 255 : b; - color = (r << 16) | (g << 8) | b | 0xff000000; + int color = (r << 16) | (g << 8) | b | 0xff000000; - - for (i = 0; i < pL; i++) { - for (j = 0; j < pW; j++) { - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - - return bm; } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/ChessPatternRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/ChessPatternRenderer.java index c840cd5d..8f627bfb 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/ChessPatternRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/ChessPatternRenderer.java @@ -1,58 +1,37 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.Version; import com.mithrilmania.blocktopograph.map.Dimension; - public class ChessPatternRenderer implements MapRenderer { public final int darkShade, lightShade;// int DARK_SHADE = 0xFF2B2B2B, LIGHT_SHADE = 0xFF585858; - ChessPatternRenderer(int darkShade, int lightShade){ + ChessPatternRenderer(int darkShade, int lightShade) { this.darkShade = darkShade; this.lightShade = lightShade; } - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - int x, z, i, j, tX, tY; + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { + + int x, z, tX, tY; int color; - for (z = bZ, tY = pY ; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { + for (z = 0, tY = pY; z < 16; z++, tY += pL) { + for (x = 0, tX = pX; x < 16; x++, tX += pW) { color = ((x + z) & 1) == 1 ? darkShade : lightShade; - for (i = 0; i < pL; i++) { - for (j = 0; j < pW; j++) { - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); + //This would get hardware acceleration. } } - - - return bm; } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/DebugRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/DebugRenderer.java index 7c505051..dcf538c9 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/DebugRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/DebugRenderer.java @@ -1,53 +1,33 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.Version; import com.mithrilmania.blocktopograph.map.Dimension; - public class DebugRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { int x, z, i, j, tX, tY; int offsetX = chunkX * dimension.chunkW; int offsetZ = chunkZ * dimension.chunkL; - for (z = bZ, tY = pY ; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { - for(i = 0; i < pL; i++){ - for(j = 0; j < pW; j++){ - bm.setPixel(tX + j, tY + i, 0xff000000 | ((offsetX + x) ^ (offsetZ + z))); + for (z = 0, tY = pY; z < 16; z++, tY += pL) { + for (x = 0, tX = pX; x < 16; x++, tX += pW) { + for (i = 0; i < pL; i++) { + for (j = 0; j < pW; j++) { + paint.setColor(0xff000000 | ((offsetX + x) ^ (offsetZ + z))); + canvas.drawPoint(tX + j, tY + i, paint); } } } } - - - return bm; } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/GrassRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/GrassRenderer.java index a908e567..a4c74063 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/GrassRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/GrassRenderer.java @@ -1,66 +1,32 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import com.mithrilmania.blocktopograph.WorldData; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; import com.mithrilmania.blocktopograph.map.Dimension; public class GrassRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); + int x, z, color, tX, tY; - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); + for (z = 0, tY = pY; z < 16; z++, tY += pL) { + for (x = 0, tX = pX; x < 16; x++, tX += pW) { - //the bottom sub-chunk is sufficient to get grass data. - TerrainChunkData data = chunk.getTerrain((byte) 0); - if(data == null || !data.load2DData()) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); + color = chunk.getGrassColor(x, z); - - int x, z, color, i, j, tX, tY; - - for (z = bZ, tY = pY; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { - - color = ((data.getGrassR(x, z) & 0xff) << 16) | ((data.getGrassG(x, z) & 0xff) << 8) | (data.getGrassB(x, z) & 0xff) | 0xff000000; - - for (i = 0; i < pL; i++) { - for (j = 0; j < pW; j++) { - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - - return bm; } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/HeightmapRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/HeightmapRenderer.java index 5c91b532..77458380 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/HeightmapRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/HeightmapRenderer.java @@ -1,82 +1,55 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import com.mithrilmania.blocktopograph.WorldData; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; import com.mithrilmania.blocktopograph.map.Dimension; public class HeightmapRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); - - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - //the bottom sub-chunk is sufficient to get heightmap data. - TerrainChunkData data = chunk.getTerrain((byte) 0); - if(data == null || !data.load2DData()) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - - TerrainChunkData dataW = cm.getChunk(chunkX - 1, chunkZ).getTerrain((byte) 0); - TerrainChunkData dataN = cm.getChunk(chunkX, chunkZ-1).getTerrain((byte) 0); - - boolean west = dataW != null && dataW.load2DData(), - north = dataN != null && dataN.load2DData(); - - int x, y, z, color, i, j, tX, tY; + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { + + Chunk dataW = worldData.getChunk(chunkX - 1, chunkZ, dimension); + Chunk dataN = worldData.getChunk(chunkX, chunkZ - 1, dimension); + + boolean west = dataW != null && !dataW.isVoid(), + north = dataN != null && !dataN.isVoid(); + + int x, y, z, color, tX, tY; int yW, yN; int r, g, b; float yNorm, yNorm2, heightShading; - for (z = bZ, tY = pY ; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { + for (z = 0, tY = pY; z < 16; z++, tY += pL) { + for (x = 0, tX = pX; x < 16; x++, tX += pW) { //smooth step function: 6x^5 - 15x^4 + 10x^3 - y = data.getHeightMapValue(x, z); + y = chunk.getHeightMapValue(x, z); + + if (y < 0) continue; yNorm = (float) y / (float) dimension.chunkH; - yNorm2 = yNorm*yNorm; - yNorm = ((6f*yNorm2) - (15f*yNorm) + 10f)*yNorm2*yNorm; + yNorm2 = yNorm * yNorm; + yNorm = ((6f * yNorm2) - (15f * yNorm) + 10f) * yNorm2 * yNorm; yW = (x == 0) ? (west ? dataW.getHeightMapValue(dimension.chunkW - 1, z) : y)//chunk edge - : data.getHeightMapValue(x - 1, z);//within chunk + : chunk.getHeightMapValue(x - 1, z);//within chunk yN = (z == 0) ? (north ? dataN.getHeightMapValue(x, dimension.chunkL - 1) : y)//chunk edge - : data.getHeightMapValue(x, z - 1);//within chunk + : chunk.getHeightMapValue(x, z - 1);//within chunk heightShading = SatelliteRenderer.getHeightShading(y, yW, yN); - r = (int) (yNorm*heightShading*256f); - g = (int) (70f*heightShading); - b = (int) (256f*(1f-yNorm)/(yNorm + 1f)); - + r = (int) (yNorm * heightShading * 256f); + g = (int) (70f * heightShading); + b = (int) (256f * (1f - yNorm) / (yNorm + 1f)); + r = r < 0 ? 0 : r > 255 ? 255 : r; g = g < 0 ? 0 : g > 255 ? 255 : g; b = b < 0 ? 0 : b > 255 ? 255 : b; @@ -84,17 +57,12 @@ public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, in color = (r << 16) | (g << 8) | b | 0xff000000; - for(i = 0; i < pL; i++){ - for(j = 0; j < pW; j++){ - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - - return bm; } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapRenderer.java index d567e222..558108f4 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapRenderer.java @@ -1,9 +1,10 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; -import com.mithrilmania.blocktopograph.chunk.ChunkData; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.Version; import com.mithrilmania.blocktopograph.map.Dimension; @@ -16,27 +17,28 @@ will just make things worse on some (most?) phones. So I guess we have to do some weird patterns to make this efficient... Currently trying to keep tile sizes constant, for bitmap recycling. Makes zooming look sharp too. + + The cat solved this :) */ + /** * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back * - * @throws Version.VersionException when the version of the chunk is unsupported. + * @param chunk The chunk. + * @param canvas Canvas for the corresponding bitmap to render to, hw acceleration on + * @param dimension Mapped dimension + * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) + * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) + * @param pX texture X pixel coord to start rendering to + * @param pY texture Y pixel coord to start rendering to + * @param pW width (X) of one block in pixels + * @param pL length (Z) of one block in pixels + * @param paint Paint instance used to draw on canvas + * @param worldData ChunkManager, some renderer needs info about its neighbor + * @throws RuntimeException when the version of the chunk is unsupported. + * TODO: reduce complicity, e.g. remove chunkManager from parameters. */ - Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException; + void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException; } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapType.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapType.java index 0524862b..a2037594 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapType.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/MapType.java @@ -42,6 +42,9 @@ public enum MapType implements DetailLevelManager.LevelType { NETHER_XRAY(new XRayRenderer()), NETHER_BLOCK_LIGHT(new BlockLightRenderer()), + + //add in 1.16.0 + NETHER_BIOME(new BiomeRenderer()), END_SATELLITE(new SatelliteRenderer()), diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/NetherRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/NetherRenderer.java index 9d0dd824..599345eb 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/NetherRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/NetherRenderer.java @@ -1,82 +1,47 @@ package com.mithrilmania.blocktopograph.map.renderer; - -import android.graphics.Bitmap; -import com.mithrilmania.blocktopograph.Log; - +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; -import com.mithrilmania.blocktopograph.map.Block; import com.mithrilmania.blocktopograph.map.Dimension; public class NetherRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); - - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - //bottom chunk must be present - TerrainChunkData floorData = chunk.getTerrain((byte) 0); - if(floorData == null || !floorData.load2DData()) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - - Chunk chunkW = cm.getChunk(chunkX - 1, chunkZ); - Chunk chunkN = cm.getChunk(chunkX, chunkZ-1); - - TerrainChunkData data; - - float shading, shadingSum, rf, gf, bf, af, a, blendR, blendG, blendB, sumRf, sumGf, sumBf; + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { + + Chunk chunkW = worldData.getChunk(chunkX - 1, chunkZ, dimension); + Chunk chunkN = worldData.getChunk(chunkX, chunkZ - 1, dimension); + + //Do you have to list all variables here in a 80s manner + // regardless of many are only used within nested loop... + + float shading, shadingSum, a, blendR, blendG, blendB, sumRf, sumGf, sumBf; int layers; int caveceil, cavefloor, cavefloorW, cavefloorN; - int x, y, z, color, i, j, tX, tY, r, g, b; - Block block; - int id, meta; int worth; - int lightValue; + int y; float heightShading, lightShading, sliceShading, avgShading; - int offset; - int stop; - int subChunk; - int stopSubChunk; - - for (z = bZ, tY = pY ; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { + for (int z = 0, tY = pY; z < 16; z++, tY += pL) { + for (int x = 0, tX = pX; x < 16; x++, tX += pW) { worth = 0; shadingSum = 0; sumRf = sumGf = sumBf = 0; layers = 1; - cavefloor = floorData.getHeightMapValue(x, z);//TODO test this + cavefloor = chunk.getHeightMapValue(x, z);//TODO test this - //See-through-multi-level-height-light-shading is the new black -- @mithrilmania while (cavefloor > 0) { caveceil = chunk.getCaveYUnderAt(x, z, cavefloor - 1); @@ -91,16 +56,10 @@ public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, in heightShading = SatelliteRenderer.getHeightShading(cavefloor, cavefloorW, cavefloorN); y = cavefloor + 1; - data = chunk.getTerrain((byte) (y / cVersion.subChunkHeight)); - - //light sources - lightValue = (data != null && data.loadTerrain()) - ? data.getBlockLightValue(x, y % cVersion.subChunkHeight, z) - : 0; //check if it is supported, default to full brightness to not lose details. - if(data.supportsBlockLightValues()) { - lightShading = (float) lightValue / 15f + 1; + if (chunk.supportsBlockLightValues()) { + lightShading = (float) chunk.getBlockLightValue(x, y, z) / 15f + 1; } else { lightShading = 2f; } @@ -115,69 +74,44 @@ public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, in shadingSum += shading; - - a = 1f; - offset = caveceil % cVersion.subChunkHeight; - stop = 0; - subChunk = caveceil / cVersion.subChunkHeight; - stopSubChunk = caveceil / cVersion.subChunkHeight; - - - subChunkLoop: for(; subChunk >= stopSubChunk; subChunk--) { - if (subChunk == stopSubChunk) stop = cavefloor % cVersion.subChunkHeight; - - data = chunk.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()) { - //start at the top of the next chunk! (current offset might differ) - offset = cVersion.subChunkHeight - 1; - continue; - } - - for (y = offset; y >= stop; y--) { - - id = data.getBlockTypeId(x, y, z) & 0xff; + for (y = caveceil; y >= cavefloor; y--) { - if (id == 0) continue;//skip air blocks + var blockTemplate = chunk.getBlockTemplate(x, y, z, 0); - meta = data.getBlockData(x, y, z) & 0xff; - block = Block.getBlock(id, meta); + if (BlockTemplates.getAirTemplate().equals(blockTemplate)) + continue;//skip air blocks - //try the default meta value: 0 - if (block == null) block = Block.getBlock(id, 0); + //try the default meta value: 0 + //if (oldBlock == null) oldBlock = KnownBlockRepr.getBlock(id, 0); - if (block == null) { - Log.w("UNKNOWN block: id: " + id + " meta: " + meta); - continue; - } + int color = blockTemplate.getColor(); + // no need to process oldBlock if it is fully transparent + if (Color.alpha(color) == 0) continue; - // no need to process block if it is fully transparent - if (block.color.alpha == 0) continue; + float rf = Color.red(color) / 255f; + float gf = Color.green(color) / 255f; + float bf = Color.blue(color) / 255f; + float af = Color.alpha(color) / 255f; - rf = block.color.red / 255f; - gf = block.color.green / 255f; - bf = block.color.blue / 255f; - af = block.color.alpha / 255f; + // alpha blend and multiply + blendR = a * af * rf * shading; + blendG = a * af * gf * shading; + blendB = a * af * bf * shading; - // alpha blend and multiply - blendR = a * af * rf * shading; - blendG = a * af * gf * shading; - blendB = a * af * bf * shading; - - sumRf += blendR; - sumGf += blendG; - sumBf += blendB; - a *= 1f - af; - - // break when an opaque block is encountered - if (block.color.alpha == 0xff) break subChunkLoop; - } + sumRf += blendR; + sumGf += blendG; + sumBf += blendB; + a *= 1f - af; - //start at the top of the next chunk! (current offset might differ) - offset = cVersion.subChunkHeight - 1; + // break when an opaque oldBlock is encountered + if (Color.alpha(color) == 0xff) break; } + //start at the top of the next chunk! (current offset might differ) + //offset = 15;//cVersion.subChunkHeight - 1; + //} layers++; @@ -186,65 +120,49 @@ public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, in avgShading = shadingSum / layers; // apply the shading - r = (int) (avgShading * sumRf / layers * 255f); - g = (int) (avgShading * sumGf / layers * 255f); - b = (int) (avgShading * sumBf / layers * 255f); - - - r = r < 0 ? 0 : r > 255 ? 255 : r; - g = g < 0 ? 0 : g > 255 ? 255 : g; - b = b < 0 ? 0 : b > 255 ? 255 : b; - - - subChunkLoop: for(subChunk = 0; subChunk < cVersion.subChunks; subChunk++) { - data = chunk.getTerrain((byte) subChunk); - if (data == null || data.loadTerrain()) break; - - for (y = 0; y < cVersion.subChunkHeight; y++) { - - //some x-ray for important stuff like portals - switch (data.getBlockTypeId(x, y, z)) { - case 52://monster spawner - r = g = b = 255; - break subChunkLoop;//max already? just stop - case 54://chest - if (worth < 90) { - worth = 90; - b = 170; - r = 240; - g = 40; - } - break; - case 115://nether wart - if (worth < 80) { - worth = 80; - r = b = 120; - g = 170; - } - break; - case 90://nether portal - if (worth < 95) { - worth = 95; - r = 60; - g = 0; - b = 170; - } - break; + int r = (int) (avgShading * sumRf / layers * 255f); + int g = (int) (avgShading * sumGf / layers * 255f); + int b = (int) (avgShading * sumBf / layers * 255f); + + + r = r < 0 ? 0 : Math.min(r, 255); + g = g < 0 ? 0 : Math.min(g, 255); + b = b < 0 ? 0 : Math.min(b, 255); + + for (y = 0; y < chunk.getHeightLimit(); y++) { + + //some x-ray for important stuff like portals + BlockTemplate blockTemplate = chunk.getBlockTemplate(x, y, z, 0); + var blockName = blockTemplate.getBlock().getName(); + if ("minecraft:mob_spawner".equals(blockName)) {//monster spawner + r = g = b = 255; + } else if ("minecraft:chest".equals(blockName)) {//chest + if (worth < 90) { + worth = 90; + b = 170; + r = 240; + g = 40; + } + } else if ("minecraft:nether_wart".equals(blockName)) {//nether wart + if (worth < 80) { + worth = 80; + r = b = 120; + g = 170; + } + } else if ("minecraft:portal".equals(blockName)) {//nether portal + if (worth < 95) { + worth = 95; + r = 60; + g = 0; + b = 170; } } } - color = (r << 16) | (g << 8) | b | 0xff000000; - - for(i = 0; i < pL; i++){ - for(j = 0; j < pW; j++){ - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor((r << 16) | (g << 8) | b | 0xff000000); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - - return bm; } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SatelliteRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SatelliteRenderer.java index c63e2ab6..ef4cc528 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SatelliteRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SatelliteRenderer.java @@ -1,186 +1,75 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; -import com.mithrilmania.blocktopograph.Log; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import androidx.annotation.NonNull; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; -import com.mithrilmania.blocktopograph.map.Block; import com.mithrilmania.blocktopograph.map.Dimension; public class SatelliteRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); - - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - //the bottom sub-chunk is sufficient to get heightmap data. - TerrainChunkData data = chunk.getTerrain((byte) 0); - if(data == null || !data.load2DData()) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - - TerrainChunkData dataW = cm.getChunk(chunkX - 1, chunkZ).getTerrain((byte) 0); - TerrainChunkData dataN = cm.getChunk(chunkX, chunkZ-1).getTerrain((byte) 0); - - boolean west = dataW != null && dataW.load2DData(), - north = dataN != null && dataN.load2DData(); - - int x, y, z, color, i, j, tX, tY; - for (z = bZ, tY = pY ; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { - - y = data.getHeightMapValue(x, z); - - color = getColumnColour(chunk, data, x, y, z, - (x == 0) ? (west ? dataW.getHeightMapValue(dimension.chunkW - 1, z) : y)//chunk edge - : data.getHeightMapValue(x - 1, z),//within chunk - (z == 0) ? (north ? dataN.getHeightMapValue(x, dimension.chunkL - 1) : y)//chunk edge - : data.getHeightMapValue(x, z - 1)//within chunk - ); - - for(i = 0; i < pL; i++){ - for(j = 0; j < pW; j++){ - bm.setPixel(tX + j, tY + i, color); - } - } - - - } - } - - return bm; - } - //calculate color of one column - private static int getColumnColour(Chunk chunk, TerrainChunkData floorData, int x, int y, int z, int heightW, int heightN) throws Version.VersionException { - float a = 1f; - float r = 0f; - float g = 0f; - float b = 0f; + static int getColumnColour(@NonNull Chunk chunk, int x, int y, int z, int heightW, int heightN) throws Version.VersionException { + float alphaRemain = 1f; + float finalR = 0f; + float finalG = 0f; + float finalB = 0f; // extract colour components as normalized doubles, from ARGB format - float biomeR = (float) (floorData.getGrassR(x, z) & 0xff) / 255f; - float biomeG = (float) (floorData.getGrassG(x, z) & 0xff) / 255f; - float biomeB = (float) (floorData.getGrassB(x, z) & 0xff) / 255f; + int grassColor = chunk.getGrassColor(x, z); + float biomeR = (float) Color.red(grassColor) / 255f; + float biomeG = (float) Color.green(grassColor) / 255f; + float biomeB = (float) Color.blue(grassColor) / 255f; - float blendR, blendG, blendB; + y--; + for (; y >= 0 && alphaRemain >= .1f; y--) { - float blockA, blockR, blockG, blockB; + var blockTemplate = chunk.getBlockTemplate(x, y, z, 0); + if (BlockTemplates.getAirTemplate().equals(blockTemplate)) continue;//skip air blocks - Block block; - int id, meta; + int color = blockTemplate.getColor(); - Version cVersion = chunk.getVersion(); - int realY = y; - int offset = y % cVersion.subChunkHeight; - int subChunk = y / cVersion.subChunkHeight; + // no need to process block if it is fully transparent + if (Color.alpha(color) == 0) continue; - TerrainChunkData data; + float blendA = Color.alpha(color) / 255f; - subChunkLoop: for(; subChunk >= 0; subChunk--) { + // alpha blend and multiply + float blendR = alphaRemain * blendA * (Color.red(color) / 255f); + float blendG = alphaRemain * blendA * (Color.green(color) / 255f); + float blendB = alphaRemain * blendA * (Color.blue(color) / 255f); - data = chunk.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()){ - //start at the top of the next chunk! (current offset might differ) - offset = cVersion.subChunkHeight - 1; - continue; + //blend biome-colored blocks + if (blockTemplate.isHasBiomeShading()) { + blendR *= biomeR; + blendG *= biomeG; + blendB *= biomeB; } - for (y = offset; y >= 0; y--) { - - id = data.getBlockTypeId(x, y, z) & 0xff; - - if (id == 0) continue;//skip air blocks - - meta = data.getBlockData(x, y, z) & 0xff; - block = Block.getBlock(id, meta); - - //try the default meta value: 0 - if (block == null) block = Block.getBlock(id, 0); - - - //TODO log null blocks to debug missing blocks - if (block == null) { - Log.w("UNKNOWN block: id: " + id + " meta: " + meta); - continue; - } - - // no need to process block if it is fully transparent - if (block.color == null || block.color.alpha == 0) continue; - - blockR = block.color.red / 255f; - blockG = block.color.green / 255f; - blockB = block.color.blue / 255f; - blockA = block.color.alpha / 255f; - - // alpha blend and multiply - blendR = a * blockA * blockR; - blendG = a * blockA * blockG; - blendB = a * blockA * blockB; - - //blend biome-colored blocks - if (block.hasBiomeShading) { - blendR *= biomeR; - blendG *= biomeG; - blendB *= biomeB; - } - - r += blendR; - g += blendG; - b += blendB; - a *= 1f - blockA; - - // break when an opaque block is encountered - if (block.color.alpha == 0xff){ - break subChunkLoop; - } - } - - //start at the top of the next chunk! (current offset might differ) - offset = cVersion.subChunkHeight - 1; + finalR += blendR; + finalG += blendG; + finalB += blendB; + alphaRemain *= 1f - blendA; } - //set y to the "real" y; consider all sub-chunks as a stack of chunks. - y = realY; - //height shading (based on slopes in terrain; height diff) float heightShading = getHeightShading(y, heightW, heightN); //go back to "surface" y++; - - TerrainChunkData surfaceChunk = chunk.getTerrain((byte) (y / cVersion.subChunkHeight)); //light sources - int lightValue = (surfaceChunk != null && surfaceChunk.loadTerrain()) - ? (surfaceChunk.getBlockLightValue(x, y % cVersion.subChunkHeight, z) & 0xff) - : 0; + int lightValue = chunk.getBlockLightValue(x, y, z) & 0xff; float lightShading = (float) lightValue / 15f + 1; //mix shading @@ -190,16 +79,45 @@ private static int getColumnColour(Chunk chunk, TerrainChunkData floorData, int //shading *= Math.max(Math.min(y / 40f, 1f), 0.2f);//shade ravines & caves, minimum *0.2 to keep some color // apply the shading - r = Math.min(Math.max(0f, r * shading), 1f); - g = Math.min(Math.max(0f, g * shading), 1f); - b = Math.min(Math.max(0f, b * shading), 1f); + finalR = Math.min(Math.max(0f, finalR * shading), 1f); + finalG = Math.min(Math.max(0f, finalG * shading), 1f); + finalB = Math.min(Math.max(0f, finalB * shading), 1f); // now we have our final RGB values as floats, convert to a packed ARGB pixel. return 0xff000000 | - ((((int) (r * 255f)) & 0xff) << 16) | - ((((int) (g * 255f)) & 0xff) << 8) | - (((int) (b * 255f)) & 0xff); + ((((int) (finalR * 255f)) & 0xff) << 16) | + ((((int) (finalG * 255f)) & 0xff) << 8) | + (((int) (finalB * 255f)) & 0xff); + } + + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { + + Chunk dataW = worldData.getChunk(chunkX - 1, chunkZ, dimension); + Chunk dataN = worldData.getChunk(chunkX, chunkZ - 1, dimension); + + boolean west = dataW != null && !dataW.isVoid(), + north = dataN != null && !dataN.isVoid(); + + for (int z = 0, tY = pY; z < 16; z++, tY += pL) { + for (int x = 0, tX = pX; x < 16; x++, tX += pW) { + + int y = chunk.getHeightMapValue(x, z); + if (y == 0) continue; + + int color = getColumnColour(chunk, x, y, z, + (x == 0) ? (west ? dataW.getHeightMapValue(dimension.chunkW - 1, z) : y)//chunk edge + : chunk.getHeightMapValue(x - 1, z),//within chunk + (z == 0) ? (north ? dataN.getHeightMapValue(x, dimension.chunkL - 1) : y)//chunk edge + : chunk.getHeightMapValue(x, z - 1)//within chunk + ); + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); + + + } + } + } // shading Amp, possible range: [0, 2] (or use negative for reverse shading) @@ -225,4 +143,4 @@ public static float getHeightShading(int height, int heightW, int heightN) { return ((float) (Math.atan(heightDiff) / Math.PI) * shadingAmp) + 1f; } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SlimeChunkRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SlimeChunkRenderer.java index 53c98511..d1c4cd75 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SlimeChunkRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/SlimeChunkRenderer.java @@ -1,53 +1,50 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.chunk.Chunk; import com.mithrilmania.blocktopograph.chunk.Version; import com.mithrilmania.blocktopograph.map.Dimension; import com.mithrilmania.blocktopograph.util.MTwister; - public class SlimeChunkRenderer implements MapRenderer { - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - int x, z, i, j, tX, tY; - - MapType.OVERWORLD_SATELLITE.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { + + int x, z, tX, tY; + + Chunk dataW = worldData.getChunk(chunkX - 1, chunkZ, dimension); + Chunk dataN = worldData.getChunk(chunkX, chunkZ - 1, dimension); + + boolean west = dataW != null && !dataW.isVoid(), + north = dataN != null && !dataN.isVoid(); + + //MapType.OVERWORLD_SATELLITE.renderer.renderToBitmap(chunk, canvas, dimension, chunkX, chunkZ, pX, pY, pW, pL, paint, version, chunkManager); boolean isSlimeChunk = isSlimeChunk(chunkX, chunkZ); int color, r, g, b, avg; //make slimeChunks much more green - for (z = bZ, tY = pY ; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { - color = bm.getPixel(tX, tY); + for (z = 0, tY = pY; z < 16; z++, tY += pL) { + for (x = 0, tX = pX; x < 16; x++, tX += pW) { + + int y = chunk.getHeightMapValue(x, z); + + color = SatelliteRenderer.getColumnColour(chunk, x, y, z, + (x == 0) ? (west ? dataW.getHeightMapValue(dimension.chunkW - 1, z) : y)//chunk edge + : chunk.getHeightMapValue(x - 1, z),//within chunk + (z == 0) ? (north ? dataN.getHeightMapValue(x, dimension.chunkL - 1) : y)//chunk edge + : chunk.getHeightMapValue(x, z - 1)//within chunk + ); r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; avg = (r + g + b) / 3; - if(isSlimeChunk){ + if (isSlimeChunk) { r = b = avg; g = (g + 0xff) >> 1; } else { @@ -55,25 +52,21 @@ public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, in } color = (color & 0xFF000000) | (r << 16) | (g << 8) | b; - for(i = 0; i < pL; i++){ - for(j = 0; j < pW; j++){ - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - return bm; } // See: https://gist.github.com/mithrilmania/00b85bf34a75fd8176342b1ad28bfccc - public static boolean isSlimeChunk(int cX, int cZ){ + private static boolean isSlimeChunk(int cX, int cZ) { // // MCPE slime-chunk checker // From Minecraft: Pocket Edition 0.15.0 (0.15.0.50_V870150050) - // Reverse engineered by @mithrilmania and @jocopa3 + // Reverse engineered by @protolambda and @jocopa3 // // NOTE: // - The world-seed doesn't seem to be incorporated into the randomness, which is very odd. @@ -82,7 +75,7 @@ public static boolean isSlimeChunk(int cX, int cZ){ // - Reverse engineering this code cost a lot of time, // please add CREDITS when you are copying this. // Copy the following into your program source: - // MCPE slime-chunk checker; reverse engineered by @mithrilmania and @jocopa3 + // MCPE slime-chunk checker; reverse engineered by @protolambda and @jocopa3 // // chunkX/Z are the chunk-coordinates, used in the DB keys etc. @@ -119,7 +112,7 @@ public static boolean isSlimeChunk(int cX, int cZ){ // Multiply with 10 (3 bits) // ---> effect: the 3 bit randomness decrease expresses a 1 in a 10 chance. - long res = (((hi_shift3 + (hi_shift3 * 0x4)) & 0xffffffffL) * 0x2) & 0xffffffffL; + long res = (((hi_shift3 + (hi_shift3 * 0x4)) & 0xffffffffL) * 0x2) & 0xffffffffL; // Final check: is the input equal to 10 times less random, but comparable, output. // Every chunk has a 1 in 10 chance to be a slime-chunk. diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/XRayRenderer.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/XRayRenderer.java index d241f8e3..b5d13fc9 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/XRayRenderer.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/renderer/XRayRenderer.java @@ -1,12 +1,16 @@ package com.mithrilmania.blocktopograph.map.renderer; -import android.graphics.Bitmap; - +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; + +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.BlockTemplates; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; import com.mithrilmania.blocktopograph.chunk.Chunk; -import com.mithrilmania.blocktopograph.chunk.ChunkManager; import com.mithrilmania.blocktopograph.chunk.Version; -import com.mithrilmania.blocktopograph.chunk.terrain.TerrainChunkData; -import com.mithrilmania.blocktopograph.map.Block; import com.mithrilmania.blocktopograph.map.Dimension; @@ -16,100 +20,68 @@ public class XRayRenderer implements MapRenderer { TODO make the X-ray viewable blocks configurable, without affecting performance too much... */ - /** - * Render a single chunk to provided bitmap (bm) - * @param cm ChunkManager, provides chunks, which provide chunk-data - * @param bm Bitmap to render to - * @param dimension Mapped dimension - * @param chunkX X chunk coordinate (x-block coord / Chunk.WIDTH) - * @param chunkZ Z chunk coordinate (z-block coord / Chunk.LENGTH) - * @param bX begin block X coordinate, relative to chunk edge - * @param bZ begin block Z coordinate, relative to chunk edge - * @param eX end block X coordinate, relative to chunk edge - * @param eZ end block Z coordinate, relative to chunk edge - * @param pX texture X pixel coord to start rendering to - * @param pY texture Y pixel coord to start rendering to - * @param pW width (X) of one block in pixels - * @param pL length (Z) of one block in pixels - * @return bm is returned back - * - * @throws Version.VersionException when the version of the chunk is unsupported. - */ - public Bitmap renderToBitmap(ChunkManager cm, Bitmap bm, Dimension dimension, int chunkX, int chunkZ, int bX, int bZ, int eX, int eZ, int pX, int pY, int pW, int pL) throws Version.VersionException { - - Chunk chunk = cm.getChunk(chunkX, chunkZ); - Version cVersion = chunk.getVersion(); - - if(cVersion == Version.ERROR) return MapType.ERROR.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - if(cVersion == Version.NULL) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - - //the bottom sub-chunk is sufficient to get heightmap data. - TerrainChunkData data; - - - int x, y, z, color, i, j, tX, tY; + public void renderToBitmap(Chunk chunk, Canvas canvas, Dimension dimension, int chunkX, int chunkZ, int pX, int pY, int pW, int pL, Paint paint, WorldData worldData) throws Version.VersionException { //render width in blocks - int rW = eX - bX; - int size2D = rW * (eZ - bZ); + int rW = 16; + int size2D = rW * (16); int index2D; - Block[] bestBlock = new Block[size2D]; + var bestBlock = new BlockTemplate[size2D]; int[] minValue = new int[size2D]; int bValue; - Block block; int average; - int r, g, b; - - int subChunk; - for(subChunk = 0; subChunk < cVersion.subChunks; subChunk++) { - data = chunk.getTerrain((byte) subChunk); - if (data == null || !data.loadTerrain()) break; - - for (z = bZ; z < eZ; z++) { - for (x = bX; x < eX; x++) { - - for (y = 0; y < cVersion.subChunkHeight; y++) { - block = Block.getBlock(data.getBlockTypeId(x, y, z) & 0xff, 0); - - index2D = ((z - bZ) * rW) + (x - bX); - if (block == null || block.id <= 1) - continue; - else if (block == Block.B_56_0_DIAMOND_ORE) { - bestBlock[index2D] = block; - break; - } else if (block == Block.B_129_0_EMERALD_ORE) bValue = 8; - else if (block == Block.B_153_0_QUARTZ_ORE) bValue = 7; - else if (block == Block.B_14_0_GOLD_ORE) bValue = 6; - else if (block == Block.B_15_0_IRON_ORE) bValue = 5; - else if (block == Block.B_73_0_REDSTONE_ORE) bValue = 4; - else if (block == Block.B_21_0_LAPIS_ORE) bValue = 3; - //else if(block == Block.COAL_ORE) bValue = 2; - //else if(b == Block.LAVA || b == Block.STATIONARY_LAVA) bValue = 1; - else bValue = 0; - - if (bValue > minValue[index2D]) { - minValue[index2D] = bValue; - bestBlock[index2D] = block; - } + BlockTemplate blockTemplate; + + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + + for (int y = 0; y < chunk.getHeightLimit(); y++) { + blockTemplate = chunk.getBlockTemplate(x, y, z, 0); + var blockName = blockTemplate.getBlock().getName(); + index2D = (z * rW) + x; + if (BlockTemplates.getAirTemplate().equals(blockTemplate)) continue; + else if ("minecraft:diamond_ore".equals(blockName)) { + bestBlock[index2D] = blockTemplate; + break; + } else if ("minecraft:emerald_ore".equals(blockName)) bValue = 8; + else if ("minecraft:quartz_ore".equals(blockName)) bValue = 7; + else if ("minecraft:gold_ore".equals(blockName)) bValue = 6; + else if ("minecraft:iron_ore".equals(blockName)) bValue = 5; + else if ("minecraft:redstone_ore".equals(blockName)) bValue = 4; + else if ("minecraft:lapis_ore".equals(blockName)) bValue = 3; + //else if(oldBlock == KnownBlockRepr.COAL_ORE) bValue = 2; + //else if(b == KnownBlockRepr.LAVA || b == KnownBlockRepr.STATIONARY_LAVA) bValue = 1; + else bValue = 0; + + if (bValue > minValue[index2D]) { + minValue[index2D] = bValue; + bestBlock[index2D] = blockTemplate; } } } } - if(subChunk == 0) return MapType.CHESS.renderer.renderToBitmap(cm, bm, dimension, chunkX, chunkZ, bX, bZ, eX, eZ, pX, pY, pW, pL); - for (z = bZ, tY = pY; z < eZ; z++, tY += pL) { - for (x = bX, tX = pX; x < eX; x++, tX += pW) { - block = bestBlock[((z - bZ) * rW) + (x - bX)]; - if (block == null || block.color == null) { +// if (y == 0) { +// MapType.CHESS.renderer.renderToBitmap(chunk, canvas, dimension, chunkX, chunkZ, pX, pY, pW, pL, paint, version, chunkManager); +// return; +// } + + for (int z = 0, tY = pY; z < 16; z++, tY += pL) { + for (int x = 0, tX = pX; x < 16; x++, tX += pW) { + blockTemplate = bestBlock[(z * rW) + x]; + int color; + if (blockTemplate == null) { color = 0xff000000; } else { - r = block.color.red; - g = block.color.green; - b = block.color.blue; + color = blockTemplate.getColor(); + + int r = Color.red(color); + int g = Color.green(color); + int b = Color.blue(color); average = (r + g + b) / 3; //make the color better recognizable @@ -126,19 +98,12 @@ else if (block == Block.B_56_0_DIAMOND_ORE) { color = (r << 16) | (g << 8) | (b) | 0xff000000; } - - - for (i = 0; i < pL; i++) { - for (j = 0; j < pW; j++) { - bm.setPixel(tX + j, tY + i, color); - } - } + paint.setColor(color); + canvas.drawRect(new Rect(tX, tY, tX + pW, tY + pL), paint); } } - - return bm; } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionChangedListener.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionChangedListener.java new file mode 100644 index 00000000..0c5b5c90 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionChangedListener.java @@ -0,0 +1,9 @@ +package com.mithrilmania.blocktopograph.map.selection; + +import android.graphics.Rect; + +public interface SelectionChangedListener { + + void onSelectionChanged(Rect selection); + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionMenuFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionMenuFragment.java new file mode 100644 index 00000000..1ad4d5e0 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionMenuFragment.java @@ -0,0 +1,248 @@ +package com.mithrilmania.blocktopograph.map.selection; + +import android.app.Activity; +import android.graphics.Rect; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.block.OldBlockRegistry; +import com.mithrilmania.blocktopograph.databinding.FragSelMenuBinding; +import com.mithrilmania.blocktopograph.map.FloatPaneFragment; +import com.mithrilmania.blocktopograph.map.edit.ChBiomeFragment; +import com.mithrilmania.blocktopograph.map.edit.EditFunction; +import com.mithrilmania.blocktopograph.map.edit.SearchAndReplaceFragment; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.lang.ref.WeakReference; + +public class SelectionMenuFragment extends FloatPaneFragment { + + public static final String TAG_SNR = "Snr"; + public static final String TAG_CHBIOME = "Chbiome"; + + @NonNull + private final Rect mSelection = new Rect(); + private FragSelMenuBinding mBinding; + @Nullable + private SelectionChangedListener mSelectionChangedListener; + + private EditFunctionEntry mEditFunctionEntry; + + private OldBlockRegistry registry; + + public static SelectionMenuFragment newInstance( + @NonNull Rect initial, @NonNull OldBlockRegistry registry, @NonNull EditFunctionEntry editFunctionEntry) { + SelectionMenuFragment fragment = new SelectionMenuFragment(); + fragment.mSelection.set(initial); + fragment.registry = registry; + fragment.mEditFunctionEntry = editFunctionEntry; + return fragment; + } + + private static boolean isSelectionChunkAligned(@NonNull Rect selection) { + return (selection.left & 0xf) == 0 && (selection.right & 0xf) == 0 + && (selection.top & 0xf) == 0 && (selection.bottom & 0xf) == 0; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + } + + public void setSelectionChangedListener(@Nullable SelectionChangedListener selectionChangedListener) { + mSelectionChangedListener = selectionChangedListener; + } + + public void onSelectionChangedOutsides(Rect rect) { + mSelection.set(rect); + mBinding.content.setSelection(rect); + } + + private void onApply(View button) { + + // It should not live alone without a selection board. + if (mSelectionChangedListener == null) { + if (mOnCloseButtonClickListener != null) + mOnCloseButtonClickListener.onCloseButtonClick(); + return; + } + + int errno = 0; + flow: + { + mSelection.left = UiUtil.readIntFromView(mBinding.content.fromXText); + mSelection.top = UiUtil.readIntFromView(mBinding.content.fromYText); + int tmp = UiUtil.readIntFromView(mBinding.content.rangeWText); + if (tmp < 1) { + errno = -1; + break flow; + } + mSelection.right = mSelection.left + tmp; + tmp = UiUtil.readIntFromView(mBinding.content.rangeHText); + if (tmp < 1) { + errno = -1; + break flow; + } + mSelection.bottom = mSelection.top + tmp; + mSelectionChangedListener.onSelectionChanged(mSelection); + } + switch (errno) { + case -1: { + Activity activity = getActivity(); + if (activity != null) + Toast.makeText(activity, + R.string.map_sel_error_size_one, Toast.LENGTH_SHORT).show(); + break; + } + } + } + + private void onChooseLampshade(@NonNull View view) { + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(view.getContext(), R.style.AppTheme)) + .setView(R.layout.dialog_lampshade) + .setTitle(R.string.map_edit_func_lampshade) + .setPositiveButton(android.R.string.ok, + (dialogInterface, i) -> mEditFunctionEntry.invokeEditFunction(EditFunction.LAMPSHADE, null)) + .setNegativeButton(android.R.string.cancel, null) + .create(); + dialog.show(); + Log.logFirebaseEvent(view.getContext(), Log.CustomFirebaseEvent.SNR_OPEN); + } + + private void onChooseSnr(View view) { + SearchAndReplaceFragment fragment = SearchAndReplaceFragment.newInstance(registry, mEditFunctionEntry); + FragmentManager fragmentManager = getMeowFragmentManager(); + fragment.show(fragmentManager, TAG_SNR); + Log.logFirebaseEvent(view.getContext(), Log.CustomFirebaseEvent.SNR_OPEN); + } + + private void onChooseDchunk(View view) { + String text = getString(R.string.map_edit_dchunk_explain); + boolean aligned = isSelectionChunkAligned(mSelection); + if (!aligned) + text += "\n\n" + getString(R.string.map_edit_dchunk_warn_not_aligned); + AlertDialog dialog = new AlertDialog.Builder(new ContextThemeWrapper(view.getContext(), R.style.AppTheme)) + .setTitle(R.string.map_edit_func_dchunk) + .setMessage(text) + .setPositiveButton(aligned ? android.R.string.ok : R.string.map_edit_dchunk_posbtn_with_auto_adjust, + ((dialogInterface, i) -> mEditFunctionEntry.invokeEditFunction(EditFunction.DCHUNK, null))) + .setNegativeButton(android.R.string.cancel, null) + .create(); + dialog.show(); + Log.logFirebaseEvent(view.getContext(), Log.CustomFirebaseEvent.DCHUNK); + } + + private void onChooseChbiome(View view) { + ChBiomeFragment fragment = ChBiomeFragment.newInstance(mEditFunctionEntry); + FragmentManager fragmentManager = getMeowFragmentManager(); + fragment.show(fragmentManager, TAG_CHBIOME); + Log.logFirebaseEvent(view.getContext(), Log.CustomFirebaseEvent.CH_BIOME); + } + + private void onChoosePicer(View view) { + mEditFunctionEntry.invokeEditFunction(EditFunction.PICER, null); + } + + @NonNull + private FragmentManager getMeowFragmentManager() { + FragmentActivity activity = getActivity(); + FragmentManager fragmentManager = null; + if (activity != null) fragmentManager = activity.getSupportFragmentManager(); + if (fragmentManager == null) fragmentManager = getChildFragmentManager(); + return fragmentManager; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + mBinding = DataBindingUtil.inflate(inflater, R.layout.frag_sel_menu, container, false); + mBinding.content.setSelection(mSelection); + mBinding.content.fromXText.addTextChangedListener(new MeowWatcher(mBinding.content.fromXText)); + mBinding.content.fromYText.addTextChangedListener(new MeowWatcher(mBinding.content.fromYText)); + mBinding.content.rangeWText.addTextChangedListener(new MeowWatcher(mBinding.content.rangeWText)); + mBinding.content.rangeHText.addTextChangedListener(new MeowWatcher(mBinding.content.rangeHText)); + mBinding.content.applyButton.setOnClickListener(this::onApply); + mBinding.content.funcLampshade.setOnClickListener(this::onChooseLampshade); + mBinding.content.funcSnr.setOnClickListener(this::onChooseSnr); + mBinding.content.funcDchunk.setOnClickListener(this::onChooseDchunk); + mBinding.content.funcChbiome.setOnClickListener(this::onChooseChbiome); + mBinding.content.funcPicer.setOnClickListener(this::onChoosePicer); + return mBinding.getRoot(); + } + + public interface EditFunctionEntry { + void invokeEditFunction(@NonNull EditFunction func, @Nullable Bundle args); + } + + private class MeowWatcher implements TextWatcher { + + private final WeakReference which; + + MeowWatcher(EditText which) { + this.which = new WeakReference<>(which); + } + + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + EditText which = this.which.get(); + if (which == null) return; + String text = editable.toString(); + int val; + try { + val = Integer.parseInt(text); + } catch (NumberFormatException e) { + return; + } + switch (which.getId()) { + case R.id.from_x_text: + if (mSelection.left == val) return; + which.removeTextChangedListener(this); + mSelection.right += val - mSelection.left; + mSelection.left = val; + break; + case R.id.from_y_text: + if (mSelection.top == val) return; + which.removeTextChangedListener(this); + mSelection.bottom += val - mSelection.top; + mSelection.top = val; + break; + case R.id.range_w_text: + if (mSelection.right - mSelection.left == val) return; + which.removeTextChangedListener(this); + mSelection.right = mSelection.left + val; + break; + case R.id.range_h_text: + if (mSelection.bottom - mSelection.top == val) return; + which.removeTextChangedListener(this); + mSelection.bottom = mSelection.top + val; + break; + } + mBinding.content.setSelection(mSelection); + which.addTextChangedListener(this); + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionView.java b/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionView.java new file mode 100644 index 00000000..41f22b7e --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/map/selection/SelectionView.java @@ -0,0 +1,671 @@ +package com.mithrilmania.blocktopograph.map.selection; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Build; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.annotation.IdRes; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; + +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.map.MCTileProvider; +import com.mithrilmania.blocktopograph.map.MapTileView; +import com.mithrilmania.blocktopograph.util.ConvertUtil; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.lang.ref.WeakReference; + +public class SelectionView extends FrameLayout { + + /** + * The view being dragged now. + */ + @Nullable + private View mDragger; + + /** + * Correction of drag begin point. + * + *

+ * It's the relative distance between the initially touched point + * and the view's left-top coordinates. + * ------------------ + * | | + * |--[ This ]--X | + * | | + * | | + * ------------------ + *

+ */ + private float mDragBeginPosCorr; + + /** + * Drag distance accumulation. + * + *

+ * If the drag distance of a given moment cannot move the selection + * at least 1 oldBlock's wide, we accumulate the distance to have a larger + * chance to move on the next round. + *

+ */ + private float mDragAccumulation; + + /** + * Current touch position. + * + *

+ * Produced in `onTouch` and consumed in `onMove`. + *

+ */ + private float mDragCurrentPos; + + /** + * Current dragging direction. + * + *

+ * Used for anti-jitter purpose. + *

+ */ + private int mDragDirection; + + /** + * Paint object used to draw selection onto canvas. + */ + private final Paint mPaint = new Paint(); + + /** + * Selection range. + */ + private final Rect mSelectionRect = new Rect(); + + /** + * The tileView we serves for. + */ + private WeakReference mTileView; + + /** + * Range of selection in pixel. + */ + private final RectF mSelectionPixelRange = new RectF(); + + /** + * Visible range of selection in pixel. + */ + private final RectF mVisiblePixelRange = new RectF(); + + /** + * Minimal distance between drag button and bound. + * -----O--------------------------- + * |----| Like this. + */ + private float BUTTON_TO_BOUND_MIN_DIST; + + /** + * The minimal non-auto-scroll distance from touched point to screen boundary. + * + *

+ * Once it's exceed the tileView would be scrolled automatically. + *

+ */ + private int MIN_DIST_TO_SCREEN_BOUND; + + private int MIN_DIST_DRAGGERS; + + private int HALF_MIN_DIST_DRAGGERS; + + /** + * Runnable used to frequently alter selection while user dragging a adjust button. + */ + private final Runnable mHoldingMover = this::onMove; + + /** + * Indicates whether a selection exists. + */ + private boolean mHasSelection; + + /** + * The selection could be changed outsides, so we need this. + */ + @Nullable + private SelectionChangedListener mSelectionChangedListener; + + public SelectionView(Context context) { + super(context); + init(context); + } + + public SelectionView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public SelectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public SelectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(context); + } + + private void init(Context context) { + + // The viewGroup has static content. + LayoutInflater.from(context).inflate(R.layout.view_selection_view, this, true); + + mPaint.setColor(Color.argb(0x80, 0, 0, 0)); + setWillNotDraw(false);// Otherwise `onDraw` won't be called. + BUTTON_TO_BOUND_MIN_DIST = UiUtil.dpToPx(context, 72); + MIN_DIST_TO_SCREEN_BOUND = UiUtil.dpToPxInt(context, 100); + MIN_DIST_DRAGGERS = UiUtil.dpToPxInt(context, 50); + HALF_MIN_DIST_DRAGGERS = MIN_DIST_DRAGGERS / 2; + + mDragger = null; + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public void onViewAdded(View child) { + switch (child.getId()) { + case R.id.left: + case R.id.right: + case R.id.top: + case R.id.bottom: + child.setOnTouchListener(this::onTouch); + break; + } + } + + private boolean onTouch(View view, MotionEvent motionEvent) { + + MapTileView tileView; + if (mTileView == null || (tileView = mTileView.get()) == null) return false; + + // If already dragging another button, disallow dragging a second one. + @IdRes int which = view.getId(); + if (mDragger != null && which != mDragger.getId()) { + // Well if we return false for an ACTION_DOWN then it won't bother popping + // Tons of confusing ACTION_MOVEs. + return false; + } + + // Set current pos. + switch (which) { + case R.id.left: + case R.id.right: + // Motion event's get x is relative to view's x. Sum 'em up. + mDragCurrentPos = view.getX() + motionEvent.getX(); + break; + case R.id.top: + case R.id.bottom: + mDragCurrentPos = view.getY() + motionEvent.getY(); + break; + } + + switch (motionEvent.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + + // Begin visual effect on the pressed button. + view.setPressed(true); + + // Show icon. + View actionIcon = getChildAt(4); + actionIcon.setVisibility(VISIBLE); + + switch (which) { + case R.id.left: + actionIcon.setRotation(270.0f); + break; + case R.id.right: + actionIcon.setRotation(90.0f); + break; + case R.id.top: + actionIcon.setRotation(0.0f); + break; + case R.id.bottom: + actionIcon.setRotation(180.0f); + break; + } + + // Prevents tileView being touched while dragging. + tileView.setTouchable(false); + + // Set current dragging item. + mDragger = view; + switch (which) { + case R.id.left: + case R.id.right: + mDragBeginPosCorr = motionEvent.getX();// - view.getX(); + break; + case R.id.top: + case R.id.bottom: + mDragBeginPosCorr = motionEvent.getY();// - view.getY(); + break; + } + mDragAccumulation = 0.0f; + mDragDirection = 0; + + // And trigger a continuous detecting. + post(mHoldingMover); + + // IMPORTANT! Forgot this once. Fuck you man, fuck you! + return true; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + + // End visual effect. + view.setPressed(false); + + // Hide icon. + getChildAt(4).setVisibility(GONE); + + // Clear & Unlock. + tileView.setTouchable(true); + mDragger = null; + return true; + + case MotionEvent.ACTION_MOVE: + //onMove(tileView, which, motionEvent); + return true; + } + + return false; + } + + private void onMove() { + + // The tileView we serves for. + MapTileView tileView; + + // If user no longer holding or we don't have a tileView to serve for. + if (mDragger == null || !isEnabled() || + mTileView == null || (tileView = mTileView.get()) == null) return; + + // Distance between view position and current holding position. + float distOnScreen; + + // Get the view to retrieve its position. + + // Won't happen. + if (mDragger == null) return; + + // Retrieve view position then get the distance and screen size. + int draggerId = mDragger.getId(); + switch (draggerId) { + case R.id.left: + case R.id.right: + // `dragged.getX() - mDragBeginPosCorr` is the current position of user's initially + // touched point of the View. + distOnScreen = mDragCurrentPos - mDragger.getX() - mDragBeginPosCorr; + break; + case R.id.top: + case R.id.bottom: + distOnScreen = mDragCurrentPos - mDragger.getY() - mDragBeginPosCorr; + break; + default: + return; + } + + flow: + { + // Amplify movement. Maybe we'd allow user to set it, or calculate based on screen + // density and tileView's scale. + float amp = 0.2f; + + //Log.d(this, "" + distOnScreen + "," + mDragCurrentPos + "," + mDragBeginPosCorr); + + // If a previous round failed to move at least 1 oldBlock's wide, + // it would accumulate the distance till in a future round we could move. + float movement = distOnScreen * amp + mDragAccumulation; + + // Translate the distance back to blocks count. + float scale = tileView.getScale(); + float pxPerBlx = scale * MCTileProvider.TILESIZE / 16; + int distanceInBlocks = Math.round(movement / pxPerBlx); + + // If it's less than a oldBlock we couldn't move, let the accumulation grow. + if (distanceInBlocks == 0) {//&& Math.abs(movement) >= 0.00001f) { + mDragAccumulation = movement; + break flow; + } + + // Anti-jitter. If the user's scrolling right carefully, we don't want it suddenly goes + // left because the view also moved and moved faster than the finger. + if (// If previous direction set, is negative to current, and current movement is short. + (distanceInBlocks < 0 && mDragDirection > 0 && distOnScreen > -10.0f) + || (distanceInBlocks > 0 && mDragDirection < 0 && distOnScreen < 10.0f)) { + // Then we do not move and clear accumulation. + mDragAccumulation = 0; + break flow; + } + + // Set direction for next round's anti-jitter. + mDragDirection = distanceInBlocks > 0 ? 1 : -1; + + // We've decided to move NOW AND TODAY clear accumulation. + mDragAccumulation = 0; + + // Alter selection. + // Selection shall be at least 1x1. + switch (draggerId) { + case R.id.left: + if (mSelectionRect.left + distanceInBlocks >= mSelectionRect.right) { + mSelectionRect.left = mSelectionRect.right - 1; + distanceInBlocks = 0; + } else mSelectionRect.left += distanceInBlocks; + break; + case R.id.right: + if (mSelectionRect.right + distanceInBlocks <= mSelectionRect.left) { + mSelectionRect.right = mSelectionRect.left + 1; + distanceInBlocks = 0; + } else mSelectionRect.right += distanceInBlocks; + break; + case R.id.top: + if (mSelectionRect.top + distanceInBlocks >= mSelectionRect.bottom) { + mSelectionRect.top = mSelectionRect.bottom - 1; + distanceInBlocks = 0; + } else mSelectionRect.top += distanceInBlocks; + break; + case R.id.bottom: + if (mSelectionRect.bottom + distanceInBlocks <= mSelectionRect.top) { + mSelectionRect.bottom = mSelectionRect.top + 1; + distanceInBlocks = 0; + } else mSelectionRect.bottom += distanceInBlocks; + break; + } + + // If no movement, return. + // It would be caused by the "Selection must be at least 1x1" rule. + // For instance in case it's already 200x1 we can't move vertically. + if (distanceInBlocks == 0) break flow; + + // Notify outsides. + if (mSelectionChangedListener != null) + mSelectionChangedListener.onSelectionChanged(mSelectionRect); + + // Should we move the underlying tileView as well? + // If touched point is near the moving direction (not the dragger position) + // then we scroll. + + int sw = getMeasuredWidth(); + int sh = getMeasuredHeight(); + int minw = Math.max(MIN_DIST_TO_SCREEN_BOUND, sw / 8); + int minh = Math.max(MIN_DIST_TO_SCREEN_BOUND, sh / 8); + + switch (draggerId) { + case R.id.left: + case R.id.right: + // (Moving right and near right bound) or + // (Moving left and near left bound) + if (mDragDirection > 0 && sw - mDragCurrentPos < minw + || (mDragDirection < 0 && mDragCurrentPos < minw) + ) + tileView.setScrollX((int) (tileView.getScrollX() + movement)); + else + requestLayout(); + break; + case R.id.top: + case R.id.bottom: + if (mDragDirection > 0 && sh - mDragCurrentPos < minh + || (mDragDirection < 0 && mDragCurrentPos < minh) + ) + tileView.setScrollY((int) (tileView.getScrollY() + movement)); + else + requestLayout(); + break; + } + } + + // Schedule the next round. + postDelayed(mHoldingMover, 40); + } + + public void setTileView(MapTileView tileView) { + mTileView = new WeakReference<>(tileView); + } + + public void beginSelection(Rect selection) { + mHasSelection = true; + mSelectionRect.set(selection); + setVisibility(VISIBLE); + requestLayout(); + } + + public void beginSelection(int centerX, int centerZ) { + + // Requires this. + MapTileView tileView; + if (mTileView == null || (tileView = mTileView.get()) == null) return; + + // Self's not visible now and not sure whether has measured dimensions. + // Use tileView's instead. + float scale = tileView.getScale(); + int w = tileView.getMeasuredWidth(); + int h = tileView.getMeasuredHeight(); + + // Selection would be a square with length of half screen dimension. + if (w > h) w = h / 4; + else w /= 4; + + // Translate to blocks. + float pxPerBlx = scale * MCTileProvider.TILESIZE / 16; + int rad = Math.round(w / pxPerBlx); + mHasSelection = true; + + // Set it. + mSelectionRect.set(centerX - rad, centerZ - rad, + centerX + rad, centerZ + rad); + setVisibility(VISIBLE); + requestLayout(); + } + + public void onSelectionChangedOutsides(Rect rect) { + mSelectionRect.set(rect); + // If the selection's far away from current viewport, + // We want tho scroll the tileView to a nearest corner of the selection. + MapTileView tileView; + if (mTileView != null && (tileView = mTileView.get()) != null) { + float pxPerBlx = tileView.getScale() * MCTileProvider.TILESIZE / 16; + RectF r = new RectF(); + r.left = (rect.left + MCTileProvider.HALF_WORLDSIZE) * pxPerBlx; + r.top = (rect.top + MCTileProvider.HALF_WORLDSIZE) * pxPerBlx; + r.right = (rect.right + MCTileProvider.HALF_WORLDSIZE) * pxPerBlx; + r.bottom = (rect.bottom + MCTileProvider.HALF_WORLDSIZE) * pxPerBlx; + int scrollX = tileView.getScrollX(); + int scrollY = tileView.getScrollY(); + int sw = getMeasuredWidth(); + int sh = getMeasuredHeight(); + RectF viewport = new RectF(scrollX, scrollY, scrollX + sw, scrollY + sh); + if (!viewport.intersect(r)) { + float hw = sw / 2.0f; + float currentX = scrollX + hw; + float hh = sh / 2.0f; + float currentY = scrollY + hh; + float dlt = ConvertUtil.distance(currentX, currentY, r.left, r.top); + float drt = ConvertUtil.distance(currentX, currentY, r.right, r.top); + float dlb = ConvertUtil.distance(currentX, currentY, r.left, r.bottom); + float drb = ConvertUtil.distance(currentX, currentY, r.right, r.bottom); + if (dlt < drt && dlt < dlb && dlt < drb) { + tileView.setScrollX((int) (r.left - hw)); + tileView.setScrollY((int) (r.top - hh)); + } else if (drt < dlb && drt < drb) { + tileView.setScrollX((int) (r.right - hw)); + tileView.setScrollY((int) (r.top - hh)); + } else if (dlb < drb) { + tileView.setScrollX((int) (r.left - hw)); + tileView.setScrollY((int) (r.bottom - hh)); + } else { + tileView.setScrollX((int) (r.right - hw)); + tileView.setScrollY((int) (r.bottom - hh)); + } + } + } + requestLayout(); + } + + public void endSelection() { + mHasSelection = false; + setVisibility(GONE); + requestLayout(); + } + + public boolean hasSelection() { + return mHasSelection; + } + + + public Rect getSelection() { + return new Rect(mSelectionRect); + } + + @Override + protected void onLayout(boolean b, int i, int i1, int i2, int i3) { + + if (!mHasSelection) return; + + float sw = getMeasuredWidth(); + float sh = getMeasuredHeight(); + + MapTileView tileView; + if (mTileView == null || (tileView = mTileView.get()) == null) return; + + float scale = tileView.getScale(); + + // Pixels per oldBlock. + float pxPerBlx = scale * MCTileProvider.TILESIZE / 16; + + // This would translate coordinate related to view, e.g. getScrollX() result, + // into coordinate related to World. + float halfWorld = pxPerBlx * MCTileProvider.HALF_WORLDSIZE; + + // These translate selection dimensions (rel. to World) to screen. + float transToScrX = (float) tileView.getScrollX() - halfWorld; + float transToScrY = (float) tileView.getScrollY() - halfWorld; + + // Draw selected range + + mSelectionPixelRange.left = pxPerBlx * mSelectionRect.left - transToScrX; + mSelectionPixelRange.top = pxPerBlx * mSelectionRect.top - transToScrY; + mSelectionPixelRange.right = pxPerBlx * mSelectionRect.right - transToScrX; + mSelectionPixelRange.bottom = pxPerBlx * mSelectionRect.bottom - transToScrY; + + // To the middle of lefter bound of on-screen selection area. + float horix = ((mSelectionPixelRange.left < 0 ? 0.0f : mSelectionPixelRange.left) + + (mSelectionPixelRange.right > sw ? sw : mSelectionPixelRange.right)) / 2.0f; + float verty = ((mSelectionPixelRange.top < 0 ? 0.0f : mSelectionPixelRange.top) + + (mSelectionPixelRange.bottom > sh ? sh : mSelectionPixelRange.bottom)) / 2.0f; + + // In case the selection's not too small. + if (mSelectionPixelRange.right - mSelectionPixelRange.left > BUTTON_TO_BOUND_MIN_DIST * 2) { + + if (horix - mSelectionPixelRange.left < BUTTON_TO_BOUND_MIN_DIST) + horix = mSelectionPixelRange.left + BUTTON_TO_BOUND_MIN_DIST; + + if (mSelectionPixelRange.right - horix < BUTTON_TO_BOUND_MIN_DIST) + horix = mSelectionPixelRange.right - BUTTON_TO_BOUND_MIN_DIST; + + } + if (mSelectionPixelRange.bottom - mSelectionPixelRange.top > BUTTON_TO_BOUND_MIN_DIST * 2) { + + if (verty - mSelectionPixelRange.top < BUTTON_TO_BOUND_MIN_DIST) + verty = mSelectionPixelRange.top + BUTTON_TO_BOUND_MIN_DIST; + + if (mSelectionPixelRange.bottom - verty < BUTTON_TO_BOUND_MIN_DIST) + verty = mSelectionPixelRange.bottom - BUTTON_TO_BOUND_MIN_DIST; + + } + + int horit = (int) mSelectionPixelRange.top; + int vertl = (int) mSelectionPixelRange.left; + int horib = (int) mSelectionPixelRange.bottom; + int vertr = (int) mSelectionPixelRange.right; + int horixi = (int) horix; + int vertyi = (int) verty; + + // Let's prevent draggers collapse together when the selection's small. + + if (horib - horit <= MIN_DIST_DRAGGERS) { + horit -= HALF_MIN_DIST_DRAGGERS; + horib += HALF_MIN_DIST_DRAGGERS; + } + + if (vertr - vertl <= MIN_DIST_DRAGGERS) { + vertl -= HALF_MIN_DIST_DRAGGERS; + vertr += HALF_MIN_DIST_DRAGGERS; + } + + // Left + View view = getChildAt(0); + int humw = view.getMeasuredWidth() / 2; + int humh = view.getMeasuredHeight() / 2; + view.layout(vertl - humw, vertyi - humh, vertl + humw, vertyi + humh); + + // Top + view = getChildAt(1); + humw = view.getMeasuredWidth() / 2; + humh = view.getMeasuredHeight() / 2; + view.layout(horixi - humw, horit - humh, horixi + humw, horit + humh); + + // Right + view = getChildAt(2); + humw = view.getMeasuredWidth() / 2; + humh = view.getMeasuredHeight() / 2; + view.layout(vertr - humw, vertyi - humh, vertr + humw, vertyi + humh); + + // Top + view = getChildAt(3); + humw = view.getMeasuredWidth() / 2; + humh = view.getMeasuredHeight() / 2; + view.layout(horixi - humw, horib - humh, horixi + humw, horib + humh); + + // Current action icon. + view = getChildAt(4); + { + int vw = view.getMeasuredWidth(); + int vh = view.getMeasuredHeight(); + int l = (getMeasuredWidth() - vw) / 2; + int t = (getMeasuredHeight() - vh) / 2; + view.layout(l, t, l + vw, t + vh); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (!mHasSelection) return; + + // Screen dimensions. + float sw = getMeasuredWidth(); + float sh = getMeasuredHeight(); + + if (!canvas.quickReject(mSelectionPixelRange, Canvas.EdgeType.BW)) { + + mVisiblePixelRange.left = (mSelectionPixelRange.left < 0.0f) ? 0.0f : mSelectionPixelRange.left; + mVisiblePixelRange.top = (mSelectionPixelRange.top < 0.0f) ? 0.0f : mSelectionPixelRange.top; + mVisiblePixelRange.right = (mSelectionPixelRange.right > sw) ? sw : mSelectionPixelRange.right; + mVisiblePixelRange.bottom = (mSelectionPixelRange.bottom > sh) ? sh : mSelectionPixelRange.bottom; + + canvas.drawRect(mVisiblePixelRange, mPaint); + } + + } + + public void setSelectionChangedListener(@Nullable SelectionChangedListener selectionChangedListener) { + mSelectionChangedListener = selectionChangedListener; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/EditorFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/EditorFragment.java index 9807ec54..5852d729 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/EditorFragment.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/EditorFragment.java @@ -3,40 +3,44 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; -import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; import android.text.Editable; -import android.text.Layout; import android.text.TextWatcher; -import com.mithrilmania.blocktopograph.Log; - -import android.util.DisplayMetrics; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; -import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; +import com.mithrilmania.blocktopograph.Log; import com.mithrilmania.blocktopograph.R; -import com.mithrilmania.blocktopograph.WorldActivity; import com.mithrilmania.blocktopograph.WorldActivityInterface; import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; -import com.mithrilmania.blocktopograph.nbt.tags.*; -import com.unnamed.b.atv.holder.SimpleViewHolder; +import com.mithrilmania.blocktopograph.nbt.tags.ByteTag; +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.DoubleTag; +import com.mithrilmania.blocktopograph.nbt.tags.FloatTag; +import com.mithrilmania.blocktopograph.nbt.tags.IntTag; +import com.mithrilmania.blocktopograph.nbt.tags.ListTag; +import com.mithrilmania.blocktopograph.nbt.tags.LongTag; +import com.mithrilmania.blocktopograph.nbt.tags.ShortTag; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; import com.unnamed.b.atv.model.TreeNode; import com.unnamed.b.atv.view.AndroidTreeView; @@ -46,545 +50,143 @@ public class EditorFragment extends Fragment { /** - * * TODO: - * + *

* - The onSomethingChanged listeners should start Asynchronous tasks - * when directly modifying NBT. - * + * when directly modifying NBT. + *

* - This editor should be refactored into parts, it grew too large. - * + *

* - The functions lack documentation. Add it. Ask @mithrilmania for now... - * */ private EditableNBT nbt; - public void setEditableNBT(EditableNBT nbt){ + public void setNbt(@NonNull EditableNBT nbt) { this.nbt = nbt; } - public static class ChainTag { + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { - public Tag parent, self; - public ChainTag(Tag parent, Tag self){ - this.parent = parent; - this.self = self; + if (nbt == null) { + Log.e(this, "No NBT data provided"); + if (getActivity() == null) return null; + //What are you doing! + TextView textView = new TextView(getActivity()); + textView.setText("Cannot load data. Close me please."); + return textView; } - } - public static class RootNodeHolder extends TreeNode.BaseNodeViewHolder{ + final View rootView = inflater.inflate(R.layout.nbt_editor, container, false); + // edit functionality + // ================================ - public RootNodeHolder(Context context) { - super(context); - } + TreeNode superRoot = TreeNode.root(); + TreeNode root = new TreeNode(nbt); + superRoot.addChild(root); + root.setExpanded(true); + root.setSelectable(false); - @Override - public View createNodeView(TreeNode node, EditableNBT value) { - final LayoutInflater inflater = LayoutInflater.from(context); + final Activity activity = getActivity(); - final View tagView = inflater.inflate(R.layout.tag_root_layout, null, false); - TextView tagName = (TextView) tagView.findViewById(R.id.tag_name); - tagName.setText(value.getRootTitle()); + root.setViewHolder(new RootNodeHolder(activity)); - return tagView; + for (Tag tag : nbt.getTags()) { + if (tag != null) + root.addChild(new TreeNode(new ChainTag(null, tag)).setViewHolder(new NBTNodeHolder(nbt, activity))); } - @Override - public void toggle(boolean active) { - } + FrameLayout frame = rootView.findViewById(R.id.nbt_editor_frame); - @Override - public int getContainerStyle() { - return R.style.TreeNodeStyleCustomRoot; - } - } + final AndroidTreeView tree = new AndroidTreeView(getActivity(), superRoot); + tree.setUse2dScroll(true); + final View treeView = tree.getView(); - public static class NBTNodeHolder extends TreeNode.BaseNodeViewHolder { + treeView.setScrollContainer(true); - private final EditableNBT nbt; + tree.setDefaultNodeLongClickListener(new TreeNode.TreeNodeLongClickListener() { + @Override + public boolean onLongClick(final TreeNode node, final Object value) { - public NBTNodeHolder(EditableNBT nbt, Context context) { - super(context); - this.nbt = nbt; - } + Log.d(this, "NBT editor: Long click!"); - @SuppressLint("SetTextI18n") - @Override - public View createNodeView(TreeNode node, final ChainTag chain) { - if(chain == null) return null; - Tag tag = chain.self; - if(tag == null) return null; + //root tag has nbt as value + if (value instanceof EditableNBT) { - final LayoutInflater inflater = LayoutInflater.from(context); + if (!nbt.enableRootModifications) { + Toast.makeText(activity, R.string.cannot_edit_root_NBT_tag, Toast.LENGTH_LONG).show(); + return true; + } - int layoutID; + AlertDialog.Builder builder = new AlertDialog.Builder(activity); - switch (tag.getType()) { - case COMPOUND: { - List value = ((CompoundTag) tag).getValue(); - if (value != null) { - for (Tag child : value) { - node.addChild(new TreeNode(new ChainTag(tag, child)).setViewHolder(new NBTNodeHolder(nbt, context))); - } - } + builder.setTitle(R.string.root_NBT_options) + .setItems(getRootNBTEditOptions(), new DialogInterface.OnClickListener() { - layoutID = R.layout.tag_compound_layout; - break; - } - case LIST: { - List value = ((ListTag) tag).getValue(); + private void showMsg(int msg) { + Toast.makeText(activity, msg, Toast.LENGTH_LONG).show(); + } - if (value != null) { - for (Tag child : value) { - node.addChild(new TreeNode(new ChainTag(tag, child)).setViewHolder(new NBTNodeHolder(nbt, context))); - } - } + public void onClick(DialogInterface dialog, int which) { + try { + RootNBTEditOption option = RootNBTEditOption.values()[which]; - layoutID = R.layout.tag_list_layout; - break; - } - case BYTE_ARRAY: { - layoutID = R.layout.tag_default_layout; - break; - } - case BYTE: { - String name = tag.getName().toLowerCase(); + switch (option) { + case ADD_NBT_TAG: { + final EditText nameText = new EditText(activity); + nameText.setHint(R.string.hint_tag_name_here); - //TODO differentiate boolean tags from byte tags better - if (name.startsWith("has") || name.startsWith("is")) { - layoutID = R.layout.tag_boolean_layout; - } else { - layoutID = R.layout.tag_byte_layout; - } - break; - } - case SHORT: - layoutID = R.layout.tag_short_layout; - break; - case INT: - layoutID = R.layout.tag_int_layout; - break; - case LONG: - layoutID = R.layout.tag_long_layout; - break; - case FLOAT: - layoutID = R.layout.tag_float_layout; - break; - case DOUBLE: - layoutID = R.layout.tag_double_layout; - break; - case STRING: - layoutID = R.layout.tag_string_layout; - break; - default: - layoutID = R.layout.tag_default_layout; - break; - } + //NBT tag type spinner + final Spinner spinner = new Spinner(activity); + ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>( + activity, android.R.layout.simple_spinner_item, NBTConstants.NBTType.editorOptions_asString); - final View tagView = inflater.inflate(layoutID, null, false); - TextView tagName = (TextView) tagView.findViewById(R.id.tag_name); - tagName.setText(tag.getName()); + spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(spinnerArrayAdapter); - switch (layoutID){ - case R.layout.tag_boolean_layout: { - final CheckBox checkBox = (CheckBox) tagView.findViewById(R.id.checkBox); - final ByteTag byteTag = (ByteTag) tag; - checkBox.setChecked(byteTag.getValue() == (byte) 1); - checkBox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() { - /** - * Called when the checked state of a compound button has changed. - * - * @param buttonView The compound button view whose state has changed. - * @param isChecked The new checked state of buttonView. - */ - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - byteTag.setValue(isChecked ? (byte) 1 : (byte) 0); - nbt.setModified(); - } - }); - break; - } - case R.layout.tag_byte_layout: { - final EditText editText = (EditText) tagView.findViewById(R.id.byteField); - final ByteTag byteTag = (ByteTag) tag; - //parse the byte as an unsigned byte - editText.setText(""+(((int) byteTag.getValue()) & 0xFF)); - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { } + //wrap editText and spinner in linear layout + LinearLayout linearLayout = new LinearLayout(activity); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setLayoutParams( + new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT, + Gravity.BOTTOM)); + linearLayout.addView(nameText); + linearLayout.addView(spinner); - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { } + //wrap layout in alert + AlertDialog.Builder alert = new AlertDialog.Builder(activity); + alert.setTitle(R.string.create_nbt_tag); + alert.setView(linearLayout); - @Override - public void afterTextChanged(Editable s) { - String sValue = s.toString(); - try { - int value = Integer.parseInt(sValue); - if(value < 0 || value > 0xff) - throw new NumberFormatException("No unsigned byte."); - byteTag.setValue((byte) value); - nbt.setModified(); - } catch (NumberFormatException e){ - editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); - } - } - }); - break; - } - case R.layout.tag_short_layout: { - final EditText editText = (EditText) tagView.findViewById(R.id.shortField); - final ShortTag shortTag = (ShortTag) tag; - editText.setText(shortTag.getValue().toString()); - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { } + //alert can create a new tag + alert.setPositiveButton(R.string.create, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { } + //new tag name + Editable newNameEditable = nameText.getText(); + String newName = (newNameEditable == null || newNameEditable.toString().equals("")) ? null : newNameEditable.toString(); - @Override - public void afterTextChanged(Editable s) { - String sValue = s.toString(); - try { - shortTag.setValue(Short.valueOf(sValue)); - nbt.setModified(); - } catch (NumberFormatException e){ - editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); - } - } - }); - break; - } - case R.layout.tag_int_layout: { - final EditText editText = (EditText) tagView.findViewById(R.id.intField); - final IntTag intTag = (IntTag) tag; - editText.setText(intTag.getValue().toString()); - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { } + //new tag type + int spinnerIndex = spinner.getSelectedItemPosition(); + NBTConstants.NBTType nbtType = NBTConstants.NBTType.editorOptions_asType[spinnerIndex]; - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { } + //create new tag + Tag newTag = NBTConstants.NBTType.newInstance(newName, nbtType); - @Override - public void afterTextChanged(Editable s) { - String sValue = s.toString(); - try { - intTag.setValue(Integer.valueOf(sValue)); - nbt.setModified(); - } catch (NumberFormatException e){ - editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); - } - } - }); - break; - } - case R.layout.tag_long_layout: { - final EditText editText = (EditText) tagView.findViewById(R.id.longField); - final LongTag longTag = (LongTag) tag; - editText.setText(longTag.getValue().toString()); - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { } + //add tag to nbt + nbt.addRootTag(newTag); + tree.addNode(node, new TreeNode(new ChainTag(null, newTag)).setViewHolder(new NBTNodeHolder(nbt, activity))); - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { } - - @Override - public void afterTextChanged(Editable s) { - String sValue = s.toString(); - try { - longTag.setValue(Long.valueOf(sValue)); - nbt.setModified(); - } catch (NumberFormatException e){ - editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); - } - } - }); - break; - } - case R.layout.tag_float_layout: { - final EditText editText = (EditText) tagView.findViewById(R.id.floatField); - final FloatTag floatTag = (FloatTag) tag; - editText.setText(floatTag.getValue().toString()); - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { } - - @Override - public void afterTextChanged(Editable s) { - String sValue = s.toString(); - try { - floatTag.setValue(Float.valueOf(sValue)); - nbt.setModified(); - } catch (NumberFormatException e){ - editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); - } - } - }); - break; - } - case R.layout.tag_double_layout: { - final EditText editText = (EditText) tagView.findViewById(R.id.doubleField); - final DoubleTag doubleTag = (DoubleTag) tag; - editText.setText(doubleTag.getValue().toString()); - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { } - - @Override - public void afterTextChanged(Editable s) { - String sValue = s.toString(); - try { - doubleTag.setValue(Double.valueOf(sValue)); - nbt.setModified(); - } catch (NumberFormatException e){ - editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); - } - } - }); - break; - } - case R.layout.tag_string_layout: { - final EditText editText = (EditText) tagView.findViewById(R.id.stringField); - final StringTag stringTag = (StringTag) tag; - editText.setText(stringTag.getValue()); - editText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { } - - @Override - public void afterTextChanged(Editable s) { - nbt.setModified(); - stringTag.setValue(s.toString()); - } - }); - break; - } - default: - break; - - } - - return tagView; - } - - @Override - public void toggle(boolean active) { - } - - @Override - public int getContainerStyle() { - return R.style.TreeNodeStyleCustom; - } - - } - - public enum NBTEditOption { - - CANCEL(R.string.edit_cancel), - COPY(R.string.edit_copy), - PASTE_OVERWRITE(R.string.edit_paste_overwrite), - PASTE_SUBTAG(R.string.edit_paste_sub_tag), - DELETE(R.string.edit_delete), - RENAME(R.string.edit_rename), - ADD_SUBTAG(R.string.edit_add_sub_tag); - - public final int stringId; - - NBTEditOption(int stringId){ - this.stringId = stringId; - } - } - - public String[] getNBTEditOptions(){ - NBTEditOption[] values = NBTEditOption.values(); - int len = values.length; - String[] options = new String[len]; - for(int i = 0; i < len; i++){ - options[i] = getString(values[i].stringId); - } - return options; - } - - public enum RootNBTEditOption { - - ADD_NBT_TAG(R.string.edit_root_add), - PASTE_SUB_TAG(R.string.edit_root_paste_sub_tag), - REMOVE_ALL_TAGS(R.string.edit_root_remove_all); - - public final int stringId; - - RootNBTEditOption(int stringId){ - this.stringId = stringId; - } - - } - - public String[] getRootNBTEditOptions(){ - RootNBTEditOption[] values = RootNBTEditOption.values(); - int len = values.length; - String[] options = new String[len]; - for(int i = 0; i < len; i++){ - options[i] = getString(values[i].stringId); - } - return options; - } - - - public static Tag clipboard; - - - //returns true if there is a tag in content with a name equals to key. - boolean checkKeyCollision(String key, List content){ - if(content == null || content.isEmpty()) return false; - if(key == null) key = ""; - String tagName; - for(Tag tag : content) { - tagName = tag.getName(); - if(tagName == null) tagName = ""; - if(tagName.equals(key)) { - return true; - } - } - return false; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - - if(nbt == null){ - new Exception("No NBT data provided").printStackTrace(); - getActivity().finish(); - - return null; - } - - final View rootView = inflater.inflate(R.layout.nbt_editor, container, false); - - // edit functionality - // ================================ - - TreeNode superRoot = TreeNode.root(); - TreeNode root = new TreeNode(nbt); - superRoot.addChild(root); - root.setExpanded(true); - root.setSelectable(false); - - - final Activity activity = getActivity(); - - root.setViewHolder(new RootNodeHolder(activity)); - - for(Tag tag : nbt.getTags()){ - root.addChild(new TreeNode(new ChainTag(null, tag)).setViewHolder(new NBTNodeHolder(nbt, activity))); - } - - FrameLayout frame = (FrameLayout) rootView.findViewById(R.id.nbt_editor_frame); - - final AndroidTreeView tree = new AndroidTreeView(getActivity(), superRoot); - tree.setUse2dScroll(true); - - final View treeView = tree.getView(); - - treeView.setScrollContainer(true); - - tree.setDefaultNodeLongClickListener(new TreeNode.TreeNodeLongClickListener() { - @Override - public boolean onLongClick(final TreeNode node, final Object value) { - - Log.d("NBT editor: Long click!"); - - - //root tag has nbt as value - if(value instanceof EditableNBT){ - - if(!nbt.enableRootModifications){ - Toast.makeText(activity, R.string.cannot_edit_root_NBT_tag, Toast.LENGTH_LONG).show(); - return true; - } - - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - - builder.setTitle(R.string.root_NBT_options) - .setItems(getRootNBTEditOptions(), new DialogInterface.OnClickListener() { - - private void showMsg(int msg){ - Toast.makeText(activity, msg, Toast.LENGTH_LONG).show(); - } - - public void onClick(DialogInterface dialog, int which) { - try { - RootNBTEditOption option = RootNBTEditOption.values()[which]; - - switch (option){ - case ADD_NBT_TAG:{ - final EditText nameText = new EditText(activity); - nameText.setHint(R.string.hint_tag_name_here); - - //NBT tag type spinner - final Spinner spinner = new Spinner(activity); - ArrayAdapter spinnerArrayAdapter = new ArrayAdapter<>( - activity, android.R.layout.simple_spinner_item, NBTConstants.NBTType.editorOptions_asString); - - spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spinner.setAdapter(spinnerArrayAdapter); - - //wrap editText and spinner in linear layout - LinearLayout linearLayout = new LinearLayout(activity); - linearLayout.setOrientation(LinearLayout.VERTICAL); - linearLayout.setLayoutParams( - new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT, - Gravity.BOTTOM)); - linearLayout.addView(nameText); - linearLayout.addView(spinner); - - //wrap layout in alert - AlertDialog.Builder alert = new AlertDialog.Builder(activity); - alert.setTitle(R.string.create_nbt_tag); - alert.setView(linearLayout); - - //alert can create a new tag - alert.setPositiveButton(R.string.create, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - - //new tag name - Editable newNameEditable = nameText.getText(); - String newName = (newNameEditable == null || newNameEditable.toString().equals("")) ? null : newNameEditable.toString(); - - //new tag type - int spinnerIndex = spinner.getSelectedItemPosition(); - NBTConstants.NBTType nbtType = NBTConstants.NBTType.editorOptions_asType[spinnerIndex]; - - //create new tag - Tag newTag = NBTConstants.NBTType.newInstance(newName, nbtType); - - //add tag to nbt - nbt.addRootTag(newTag); - tree.addNode(node, new TreeNode(new ChainTag(null, newTag)).setViewHolder(new NBTNodeHolder(nbt, activity))); - - nbt.setModified(); + nbt.setModified(); } }); @@ -592,7 +194,7 @@ public void onClick(DialogInterface dialog, int whichButton) { //or alert is cancelled alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - Log.d("NBT tag creation cancelled"); + Log.d(this, "NBT tag creation cancelled"); } }); @@ -601,7 +203,7 @@ public void onClick(DialogInterface dialog, int whichButton) { return; } case PASTE_SUB_TAG: { - if(clipboard == null){ + if (clipboard == null) { showMsg(R.string.clipboard_is_empty); return; } @@ -613,7 +215,7 @@ public void onClick(DialogInterface dialog, int whichButton) { return; } - case REMOVE_ALL_TAGS:{ + case REMOVE_ALL_TAGS: { //wrap layout in alert AlertDialog.Builder alert = new AlertDialog.Builder(activity); @@ -626,10 +228,10 @@ public void onClick(DialogInterface dialog, int whichButton) { List children = new ArrayList<>(node.getChildren()); //new tag name - for(TreeNode child : children){ + for (TreeNode child : children) { tree.removeNode(child); Object childValue = child.getValue(); - if(childValue != null && childValue instanceof ChainTag) + if (childValue instanceof ChainTag) nbt.removeRootTag(((ChainTag) childValue).self); } nbt.setModified(); @@ -640,7 +242,7 @@ public void onClick(DialogInterface dialog, int whichButton) { //or alert is cancelled alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - Log.d("NBT tag creation cancelled"); + Log.d(this, "NBT tag creation cancelled"); } }); @@ -649,10 +251,10 @@ public void onClick(DialogInterface dialog, int whichButton) { break; } default: { - Log.d("User clicked unknown NBTEditOption! "+option.name()); + Log.d(this, "User clicked unknown NBTEditOption! " + option.name()); } } - } catch (Exception e){ + } catch (Exception e) { showMsg(R.string.failed_to_do_NBT_change); } } @@ -662,7 +264,7 @@ public void onClick(DialogInterface dialog, int whichButton) { return true; - } else if(value instanceof ChainTag){ + } else if (value instanceof ChainTag) { //other tags have a chain-tag as value @@ -671,23 +273,23 @@ public void onClick(DialogInterface dialog, int whichButton) { builder.setTitle(R.string.nbt_tag_options) .setItems(getNBTEditOptions(), new DialogInterface.OnClickListener() { - private void showMsg(int msg){ + private void showMsg(int msg) { Toast.makeText(activity, msg, Toast.LENGTH_LONG).show(); } @SuppressWarnings("unchecked") public void onClick(DialogInterface dialog, int which) { - try{ + try { NBTEditOption editOption = NBTEditOption.values()[which]; final Tag parent = ((ChainTag) value).parent; final Tag self = ((ChainTag) value).self; - if(self == null) return;//WTF? + if (self == null) return;//WTF? - if(editOption == null) return;//WTF? + if (editOption == null) return;//WTF? - switch (editOption){ + switch (editOption) { case CANCEL: { return; } @@ -696,12 +298,12 @@ public void onClick(DialogInterface dialog, int which) { return; } case PASTE_OVERWRITE: { - if(clipboard == null){ + if (clipboard == null) { showMsg(R.string.clipboard_is_empty); return; } - if(parent == null){ + if (parent == null) { //it is one of the children of the root node nbt.removeRootTag(self); Tag copy = clipboard.getDeepCopy(); @@ -720,7 +322,7 @@ public void onClick(DialogInterface dialog, int which) { } case COMPOUND: { content = ((CompoundTag) parent).getValue(); - if(checkKeyCollision(clipboard.getName(), content)){ + if (checkKeyCollision(clipboard.getName(), content)) { showMsg(R.string.clipboard_key_exists_in_compound); return; } @@ -731,7 +333,7 @@ public void onClick(DialogInterface dialog, int which) { return; } } - if(content != null){ + if (content != null) { content.remove(self); Tag copy = clipboard.getDeepCopy(); content.add(copy); @@ -739,13 +341,13 @@ public void onClick(DialogInterface dialog, int which) { tree.removeNode(node); nbt.setModified(); return; - } - else showMsg(R.string.error_cannot_overwrite_in_empty_parent); + } else + showMsg(R.string.error_cannot_overwrite_in_empty_parent); return; } } case PASTE_SUBTAG: { - if(clipboard == null){ + if (clipboard == null) { showMsg(R.string.clipboard_is_empty); return; } @@ -758,7 +360,7 @@ public void onClick(DialogInterface dialog, int which) { } case COMPOUND: { content = ((CompoundTag) self).getValue(); - if(checkKeyCollision(clipboard.getName(), content)){ + if (checkKeyCollision(clipboard.getName(), content)) { showMsg(R.string.clipboard_key_exists_in_compound); return; } @@ -769,7 +371,7 @@ public void onClick(DialogInterface dialog, int which) { return; } } - if(content == null){ + if (content == null) { content = new ArrayList<>(); self.setValue(content); } @@ -782,7 +384,7 @@ public void onClick(DialogInterface dialog, int which) { return; } case DELETE: { - if(parent == null){ + if (parent == null) { //it is one of the children of the root node tree.removeNode(node); nbt.removeRootTag(self); @@ -791,26 +393,26 @@ public void onClick(DialogInterface dialog, int which) { } ArrayList content; - switch (parent.getType()){ - case LIST:{ + switch (parent.getType()) { + case LIST: { content = ((ListTag) parent).getValue(); break; } - case COMPOUND:{ + case COMPOUND: { content = ((CompoundTag) parent).getValue(); break; } - default:{ + default: { showMsg(R.string.error_cannot_overwrite_tag_unknow_parent_type); return; } } - if(content != null){ + if (content != null) { content.remove(self); tree.removeNode(node); nbt.setModified(); - } - else showMsg(R.string.error_cannot_remove_from_empty_list); + } else + showMsg(R.string.error_cannot_remove_from_empty_list); return; } case RENAME: { @@ -827,9 +429,8 @@ public void onClick(DialogInterface dialog, int whichButton) { Editable newNameEditable = edittext.getText(); String newName = (newNameEditable == null || newNameEditable.toString().equals("")) ? null : newNameEditable.toString(); - if(parent != null - && parent instanceof CompoundTag - && checkKeyCollision(newName, ((CompoundTag) parent).getValue())){ + if (parent instanceof CompoundTag + && checkKeyCollision(newName, ((CompoundTag) parent).getValue())) { showMsg(R.string.error_parent_already_contains_child_with_same_key); return; } @@ -846,7 +447,7 @@ && checkKeyCollision(newName, ((CompoundTag) parent).getValue())){ alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - Log.d("Cancelled rename NBT tag"); + Log.d(this, "Cancelled rename NBT tag"); } }); @@ -855,9 +456,9 @@ public void onClick(DialogInterface dialog, int whichButton) { return; } case ADD_SUBTAG: { - switch (self.getType()){ + switch (self.getType()) { case LIST: - case COMPOUND:{ + case COMPOUND: { final EditText nameText = new EditText(activity); nameText.setHint(R.string.hint_tag_name_here); @@ -899,21 +500,19 @@ public void onClick(DialogInterface dialog, int whichButton) { ArrayList content; - if(self instanceof CompoundTag) { + if (self instanceof CompoundTag) { content = ((CompoundTag) self).getValue(); - if(checkKeyCollision(newName, content)){ + if (checkKeyCollision(newName, content)) { showMsg(R.string.error_key_already_exists_in_compound); return; } - } - else if(self instanceof ListTag){ + } else if (self instanceof ListTag) { content = ((ListTag) self).getValue(); - } - else return;//WTF? + } else return;//WTF? - if(content == null){ + if (content == null) { content = new ArrayList<>(); self.setValue(content); } @@ -922,10 +521,12 @@ else if(self instanceof ListTag){ Tag newTag = NBTConstants.NBTType.newInstance(newName, nbtType); //add tag to nbt - content.add(newTag); - tree.addNode(node, new TreeNode(new ChainTag(self, newTag)).setViewHolder(new NBTNodeHolder(nbt, activity))); + if (newTag != null) { + content.add(newTag); + tree.addNode(node, new TreeNode(new ChainTag(self, newTag)).setViewHolder(new NBTNodeHolder(nbt, activity))); - nbt.setModified(); + nbt.setModified(); + } } }); @@ -933,7 +534,7 @@ else if(self instanceof ListTag){ //or alert is cancelled alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - Log.d("NBT tag creation cancelled"); + Log.d(this, "NBT tag creation cancelled"); } }); @@ -942,14 +543,14 @@ public void onClick(DialogInterface dialog, int whichButton) { return; } - default:{ + default: { showMsg(R.string.sub_tags_only_add_compound_list); return; } } } default: { - Log.d("User clicked unknown NBTEditOption! "+editOption.name()); + Log.d(this, "User clicked unknown NBTEditOption! " + editOption.name()); } } @@ -969,16 +570,15 @@ public void onClick(DialogInterface dialog, int whichButton) { frame.addView(treeView, 0); - // save functionality // ================================ - FloatingActionButton fabSaveNBT = (FloatingActionButton) rootView.findViewById(R.id.fab_save_nbt); + FloatingActionButton fabSaveNBT = rootView.findViewById(R.id.fab_save_nbt); assert fabSaveNBT != null; fabSaveNBT.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { - if(!nbt.isModified()){ + if (!nbt.isModified()) { Snackbar.make(view, R.string.no_data_changed_nothing_to_save, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } else { @@ -988,22 +588,23 @@ public void onClick(final View view) { .setIcon(R.drawable.ic_action_save_b) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - Snackbar.make(view, "Saving NBT data...", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - if(nbt.save()){ - //nbt is not "modified" anymore, in respect to the new saved data - nbt.modified = false; - - Snackbar.make(view, "Saved NBT data!", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - ((WorldActivityInterface) activity).logFirebaseEvent(WorldActivity.CustomFirebaseEvent.NBT_EDITOR_SAVE); - } else { - Snackbar.make(view, "Error: failed to save the NBT data.", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - }}) - .setNegativeButton(android.R.string.no, null).show(); + public void onClick(DialogInterface dialog, int whichButton) { + Snackbar.make(view, "Saving NBT data...", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + if (nbt.save()) { + //nbt is not "modified" anymore, in respect to the new saved data + nbt.modified = false; + + Snackbar.make(view, "Saved NBT data!", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + Log.logFirebaseEvent(activity, Log.CustomFirebaseEvent.NBT_EDITOR_SAVE); + } else { + Snackbar.make(view, "Error: failed to save the NBT data.", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } + } + }) + .setNegativeButton(android.R.string.no, null).show(); } } @@ -1012,6 +613,425 @@ public void onClick(DialogInterface dialog, int whichButton) { return rootView; } + public static class RootNodeHolder extends TreeNode.BaseNodeViewHolder { + + + public RootNodeHolder(Context context) { + super(context); + } + + @Override + public View createNodeView(TreeNode node, EditableNBT value) { + + final LayoutInflater inflater = LayoutInflater.from(context); + + final View tagView = inflater.inflate(R.layout.tag_root_layout, null, false); + TextView tagName = tagView.findViewById(R.id.tag_name); + tagName.setText(value.getRootTitle()); + + return tagView; + } + + @Override + public void toggle(boolean active) { + } + + @Override + public int getContainerStyle() { + return R.style.TreeNodeStyleCustomRoot; + } + } + + + public static class NBTNodeHolder extends TreeNode.BaseNodeViewHolder { + + private final EditableNBT nbt; + + public NBTNodeHolder(EditableNBT nbt, Context context) { + super(context); + this.nbt = nbt; + } + + @SuppressLint("SetTextI18n") + @Override + public View createNodeView(TreeNode node, final ChainTag chain) { + + if (chain == null) return null; + Tag tag = chain.self; + if (tag == null) return null; + + final LayoutInflater inflater = LayoutInflater.from(context); + + int layoutID; + + switch (tag.getType()) { + case COMPOUND: { + List value = ((CompoundTag) tag).getValue(); + if (value != null) { + for (Tag child : value) { + node.addChild(new TreeNode(new ChainTag(tag, child)).setViewHolder(new NBTNodeHolder(nbt, context))); + } + } + + layoutID = R.layout.tag_compound_layout; + break; + } + case LIST: { + List value = ((ListTag) tag).getValue(); + + if (value != null) { + for (Tag child : value) { + node.addChild(new TreeNode(new ChainTag(tag, child)).setViewHolder(new NBTNodeHolder(nbt, context))); + } + } + + layoutID = R.layout.tag_list_layout; + break; + } + case BYTE_ARRAY: { + layoutID = R.layout.tag_default_layout; + break; + } + case BYTE: { + String name = tag.getName(); + if (name == null) name = ""; + else name = name.toLowerCase(); + + //TODO differentiate boolean tags from byte tags better + if (name.startsWith("has") || name.startsWith("is")) { + layoutID = R.layout.tag_boolean_layout; + } else { + layoutID = R.layout.tag_byte_layout; + } + break; + } + case SHORT: + layoutID = R.layout.tag_short_layout; + break; + case INT: + layoutID = R.layout.tag_int_layout; + break; + case LONG: + layoutID = R.layout.tag_long_layout; + break; + case FLOAT: + layoutID = R.layout.tag_float_layout; + break; + case DOUBLE: + layoutID = R.layout.tag_double_layout; + break; + case STRING: + layoutID = R.layout.tag_string_layout; + break; + default: + layoutID = R.layout.tag_default_layout; + break; + } + + final View tagView = inflater.inflate(layoutID, null, false); + TextView tagName = tagView.findViewById(R.id.tag_name); + tagName.setText(tag.getName()); + + switch (layoutID) { + case R.layout.tag_boolean_layout: { + final CheckBox checkBox = tagView.findViewById(R.id.checkBox); + final ByteTag byteTag = (ByteTag) tag; + checkBox.setChecked(byteTag.getValue() == (byte) 1); + checkBox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() { + /** + * Called when the checked state of a compound button has changed. + * + * @param buttonView The compound button view whose state has changed. + * @param isChecked The new checked state of buttonView. + */ + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + byteTag.setValue(isChecked ? (byte) 1 : (byte) 0); + nbt.setModified(); + } + }); + break; + } + case R.layout.tag_byte_layout: { + final EditText editText = tagView.findViewById(R.id.byteField); + final ByteTag byteTag = (ByteTag) tag; + //parse the byte as an unsigned byte + editText.setText("" + (((int) byteTag.getValue()) & 0xFF)); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + String sValue = s.toString(); + try { + int value = Integer.parseInt(sValue); + if (value < 0 || value > 0xff) + throw new NumberFormatException("No unsigned byte."); + byteTag.setValue((byte) value); + nbt.setModified(); + } catch (NumberFormatException e) { + editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); + } + } + }); + break; + } + case R.layout.tag_short_layout: { + final EditText editText = tagView.findViewById(R.id.shortField); + final ShortTag shortTag = (ShortTag) tag; + editText.setText(shortTag.getValue().toString()); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + String sValue = s.toString(); + try { + shortTag.setValue(Short.valueOf(sValue)); + nbt.setModified(); + } catch (NumberFormatException e) { + editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); + } + } + }); + break; + } + case R.layout.tag_int_layout: { + final EditText editText = tagView.findViewById(R.id.intField); + final IntTag intTag = (IntTag) tag; + editText.setText(intTag.getValue().toString()); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + String sValue = s.toString(); + try { + intTag.setValue(Integer.valueOf(sValue)); + nbt.setModified(); + } catch (NumberFormatException e) { + editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); + } + } + }); + break; + } + case R.layout.tag_long_layout: { + final EditText editText = tagView.findViewById(R.id.longField); + final LongTag longTag = (LongTag) tag; + editText.setText(longTag.getValue().toString()); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + String sValue = s.toString(); + try { + longTag.setValue(Long.valueOf(sValue)); + nbt.setModified(); + } catch (NumberFormatException e) { + editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); + } + } + }); + break; + } + case R.layout.tag_float_layout: { + final EditText editText = tagView.findViewById(R.id.floatField); + final FloatTag floatTag = (FloatTag) tag; + editText.setText(floatTag.getValue().toString()); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + String sValue = s.toString(); + try { + floatTag.setValue(Float.valueOf(sValue)); + nbt.setModified(); + } catch (NumberFormatException e) { + editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); + } + } + }); + break; + } + case R.layout.tag_double_layout: { + final EditText editText = tagView.findViewById(R.id.doubleField); + final DoubleTag doubleTag = (DoubleTag) tag; + editText.setText(doubleTag.getValue().toString()); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + String sValue = s.toString(); + try { + doubleTag.setValue(Double.valueOf(sValue)); + nbt.setModified(); + } catch (NumberFormatException e) { + editText.setError(String.format(context.getString(R.string.x_is_invalid), sValue)); + } + } + }); + break; + } + case R.layout.tag_string_layout: { + final EditText editText = tagView.findViewById(R.id.stringField); + final StringTag stringTag = (StringTag) tag; + editText.setText(stringTag.getValue()); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + nbt.setModified(); + stringTag.setValue(s.toString()); + } + }); + break; + } + default: + break; + + } + + return tagView; + } + + @Override + public void toggle(boolean active) { + } + + @Override + public int getContainerStyle() { + return R.style.TreeNodeStyleCustom; + } + + } + + public enum NBTEditOption { + + CANCEL(R.string.edit_cancel), + COPY(R.string.edit_copy), + PASTE_OVERWRITE(R.string.edit_paste_overwrite), + PASTE_SUBTAG(R.string.edit_paste_sub_tag), + DELETE(R.string.edit_delete), + RENAME(R.string.edit_rename), + ADD_SUBTAG(R.string.edit_add_sub_tag); + + public final int stringId; + + NBTEditOption(int stringId) { + this.stringId = stringId; + } + } + + public String[] getNBTEditOptions() { + NBTEditOption[] values = NBTEditOption.values(); + int len = values.length; + String[] options = new String[len]; + for (int i = 0; i < len; i++) { + options[i] = getString(values[i].stringId); + } + return options; + } + + public enum RootNBTEditOption { + + ADD_NBT_TAG(R.string.edit_root_add), + PASTE_SUB_TAG(R.string.edit_root_paste_sub_tag), + REMOVE_ALL_TAGS(R.string.edit_root_remove_all); + + public final int stringId; + + RootNBTEditOption(int stringId) { + this.stringId = stringId; + } + + } + + public String[] getRootNBTEditOptions() { + RootNBTEditOption[] values = RootNBTEditOption.values(); + int len = values.length; + String[] options = new String[len]; + for (int i = 0; i < len; i++) { + options[i] = getString(values[i].stringId); + } + return options; + } + + + public static Tag clipboard; + + + //returns true if there is a tag in content with a name equals to key. + boolean checkKeyCollision(String key, List content) { + if (content == null || content.isEmpty()) return false; + if (key == null) key = ""; + String tagName; + for (Tag tag : content) { + tagName = tag.getName(); + if (tagName == null) tagName = ""; + if (tagName.equals(key)) { + return true; + } + } + return false; + } + + public static class ChainTag { + + public Tag parent, self; + + public ChainTag(Tag parent, @NonNull Tag self) { + this.parent = parent; + this.self = self; + } + } + @Override public void onStart() { @@ -1022,7 +1042,7 @@ public void onStart() { Bundle bundle = new Bundle(); bundle.putString("title", nbt.getRootTitle()); - ((WorldActivityInterface) getActivity()).logFirebaseEvent(WorldActivity.CustomFirebaseEvent.NBT_EDITOR_OPEN, bundle); + Log.logFirebaseEvent(getActivity(), Log.CustomFirebaseEvent.NBT_EDITOR_OPEN, bundle); } @Override diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/InventoryHolder.java b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/InventoryHolder.java new file mode 100644 index 00000000..3b0332ba --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/InventoryHolder.java @@ -0,0 +1,159 @@ +package com.mithrilmania.blocktopograph.nbt; + +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.nbt.tags.ByteTag; +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.ListTag; +import com.mithrilmania.blocktopograph.nbt.tags.ShortTag; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; + +public final class InventoryHolder { + + private ListTag mContent; + + public static InventoryHolder readFromPlayer(CompoundTag player) { + Tag tag = player.getChildTagByKey(Keys.INVENTORY); + if (!(tag instanceof ListTag)) return null; + InventoryHolder ret = new InventoryHolder(); + ret.mContent = (ListTag) tag; + return ret; + } + + private InventoryHolder() { + } + + public ListTag getContent() { + return mContent; + } + + @Nullable + public Item getItemOfSlot(short slot) { + for (Tag tag : mContent.getValue()) { + if (!(tag instanceof CompoundTag)) continue; + CompoundTag itemTag = (CompoundTag) tag; + Tag sub = itemTag.getChildTagByKey(Keys.INV_SLOT); +// if(sub instanceof ShortTag) { +// Short sh = ((ShortTag) sub).getValue(); +// if (sh == null) continue; +// if (slot == sh) return new Item(itemTag); +// } +// else + if (sub instanceof ByteTag) { + Byte by = ((ByteTag) sub).getValue(); + if (by == null) continue; + if (slot == by) return new Item(itemTag); + } + } + return null; + } + + public static class Item { + + private final CompoundTag mContent; + + private Item(CompoundTag content) { + mContent = content; + } + +// private Item() { +// mContent = new CompoundTag(Keys.INVENTORY, new ArrayList<>(5)); +// //mContent. +// } + + @Nullable + public String getName() { + Tag tag = mContent.getChildTagByKey(Keys.INV_NAME); + if (!(tag instanceof StringTag)) return null; + StringTag curr = (StringTag) tag; + return curr.getValue(); + } + + public boolean setName(String name) { + Tag tag = mContent.getChildTagByKey(Keys.INV_NAME); + if (!(tag instanceof StringTag)) return false; + StringTag curr = (StringTag) tag; + curr.setValue(name); + return true; + } + + @Nullable + public Short getId() { + Tag tag = mContent.getChildTagByKey(Keys.INV_ID); + if (!(tag instanceof ShortTag)) return null; + ShortTag curr = (ShortTag) tag; + return curr.getValue(); + } + + public boolean setId(short id) { + Tag tag = mContent.getChildTagByKey(Keys.INV_ID); + if (!(tag instanceof ShortTag)) return false; + ShortTag curr = (ShortTag) tag; + curr.setValue(id); + return true; + } + + @Nullable + public Byte getCount() { + Tag tag = mContent.getChildTagByKey(Keys.INV_COUNT); + if (!(tag instanceof ByteTag)) return null; + ByteTag curr = (ByteTag) tag; + return curr.getValue(); + } + + public boolean setCount(byte count) { + Tag tag = mContent.getChildTagByKey(Keys.INV_COUNT); + if (!(tag instanceof ByteTag)) return false; + ByteTag curr = (ByteTag) tag; + curr.setValue(count); + return true; + } + + @Nullable + public Short getDamage() { + Tag tag = mContent.getChildTagByKey(Keys.INV_DAMAGE); + if (!(tag instanceof ShortTag)) return null; + ShortTag curr = (ShortTag) tag; + return curr.getValue(); + } + + public boolean setDamage(short damage) { + Tag tag = mContent.getChildTagByKey(Keys.INV_DAMAGE); + if (!(tag instanceof ShortTag)) return false; + ShortTag curr = (ShortTag) tag; + curr.setValue(damage); + return true; + } + +// @Nullable +// public Short getSlot() { +// Tag tag = mContent.getChildTagByKey(Keys.INV_SLOT); +// if (!(tag instanceof ShortTag)) return null; +// ShortTag curr = (ShortTag) tag; +// return curr.getValue(); +// } +// +// public boolean setSlot(short slot) { +// Tag tag = mContent.getChildTagByKey(Keys.INV_SLOT); +// if (!(tag instanceof ShortTag)) return false; +// ShortTag curr = (ShortTag) tag; +// curr.setValue(slot); +// return true; +// } + + @Nullable + public ItemTag getItemTag() { + Tag tag = mContent.getChildTagByKey(Keys.INV_TAG); + if (tag == null) { + ItemTag itemTag = new ItemTag(); + mContent.getValue().add(itemTag.getContent()); + return itemTag; + } + if (!(tag instanceof CompoundTag)) return null; + CompoundTag curr = (CompoundTag) tag; + return new ItemTag(curr); + } + + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/ItemTag.java b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/ItemTag.java new file mode 100644 index 00000000..d26bf23d --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/ItemTag.java @@ -0,0 +1,179 @@ +package com.mithrilmania.blocktopograph.nbt; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.mithrilmania.blocktopograph.nbt.tags.CompoundTag; +import com.mithrilmania.blocktopograph.nbt.tags.IntTag; +import com.mithrilmania.blocktopograph.nbt.tags.ListTag; +import com.mithrilmania.blocktopograph.nbt.tags.LongTag; +import com.mithrilmania.blocktopograph.nbt.tags.StringTag; +import com.mithrilmania.blocktopograph.nbt.tags.Tag; + +import java.util.ArrayList; + +public class ItemTag { + + private final CompoundTag mContent; + private ListTag mPages; + + ItemTag() { + ArrayList tags = new ArrayList<>(); + mContent = new CompoundTag(Keys.INV_TAG, tags); + } + + ItemTag(CompoundTag content) { + mContent = content; + } + + @Nullable + private String getStringEntry(@NonNull String key) { + Tag tag = mContent.getChildTagByKey(key); + if (!(tag instanceof StringTag)) return null; + return ((StringTag) tag).getValue(); + } + + private static boolean setStringEntry(@NonNull CompoundTag parent, @NonNull String key, @NonNull String val) { + Tag tag = parent.getChildTagByKey(key); + if (tag == null) { + StringTag curr = new StringTag(key, val); + parent.getValue().add(curr); + return true; + } + if (!(tag instanceof StringTag)) return false; + ((StringTag) tag).setValue(val); + return true; + } + + @Nullable + public Long getId() { + Tag tag = mContent.getChildTagByKey(Keys.I_BOOK_ID); + if (!(tag instanceof LongTag)) return null; + return ((LongTag) tag).getValue(); + } + + public boolean setId(long id) { + Tag tag = mContent.getChildTagByKey(Keys.I_BOOK_ID); + if (tag == null) { + LongTag curr = new LongTag(Keys.I_BOOK_ID, id); + mContent.getValue().add(curr); + return true; + } + if (!(tag instanceof LongTag)) return false; + ((LongTag) tag).setValue(id); + return true; + } + + @Nullable + public Integer getGeneration() { + Tag tag = mContent.getChildTagByKey(Keys.I_BOOK_GENERATION); + if (!(tag instanceof IntTag)) return null; + return ((IntTag) tag).getValue(); + } + + public boolean setGeneration(int generation) { + Tag tag = mContent.getChildTagByKey(Keys.I_BOOK_GENERATION); + if (tag == null) { + LongTag curr = new LongTag(Keys.I_BOOK_GENERATION, generation); + mContent.getValue().add(curr); + return true; + } + if (!(tag instanceof IntTag)) return false; + ((IntTag) tag).setValue(generation); + return true; + } + + @Nullable + public String getAuthor() { + return getStringEntry(Keys.I_BOOK_AUTHOR); + } + + public boolean setAuthor(String author) { + return setStringEntry(mContent, Keys.I_BOOK_AUTHOR, author); + } + + @Nullable + public String getTitle() { + return getStringEntry(Keys.I_BOOK_TITLE); + } + + public boolean setTitle(String title) { + return setStringEntry(mContent, Keys.I_BOOK_TITLE, title); + } + + @Nullable + public String getXuid() { + return getStringEntry(Keys.I_BOOK_XUID); + } + + public boolean setXuid(String xuid) { + return setStringEntry(mContent, Keys.I_BOOK_XUID, xuid); + } + + /** + * Try to load pages of a book item. + * + * @return false if the same tag of wrong type exists, otherwise true. + */ + private boolean preparePages() { + if (mPages != null) return true; + Tag tag = mContent.getChildTagByKey(Keys.I_BOOK_PAGES); + if (tag instanceof ListTag) { + mPages = (ListTag) tag; + return true; + } else return tag == null; + } + + public int getPagesCount() { + preparePages(); + if (mPages == null) return -1; + return mPages.getValue().size(); + } + + private static void addPage(ArrayList list) { + ArrayList subs = new ArrayList<>(4); + CompoundTag tag = new CompoundTag("", subs); + setStringEntry(tag, Keys.I_BOOK_PAGES_PHOTONAME, ""); + setStringEntry(tag, Keys.I_BOOK_PAGES_TEXT, ""); + list.add(tag); + } + + @Nullable + public CompoundTag getPage(int index) { + if (!preparePages()) return null; + if (mPages == null) { + mPages = new ListTag(Keys.I_BOOK_PAGES, new ArrayList<>(Math.max(index, 4))); + mContent.getValue().add(mPages); + } + ArrayList pages = mPages.getValue(); + for (int i = pages.size(); i <= index; i++) addPage(pages); + Tag tag = pages.get(index); + if (tag instanceof CompoundTag) return (CompoundTag) tag; + return null; + } + + public static boolean setPageText(CompoundTag page, String text) { + return setStringEntry(page, Keys.I_BOOK_PAGES_TEXT, text); + } + + public static boolean setPageUrl(@NonNull CompoundTag page, @NonNull String url) { + Tag tag = page.getChildTagByKey(Keys.I_BOOK_PAGES_CLICK); + CompoundTag event; + if (tag == null) { + event = new CompoundTag(Keys.I_BOOK_PAGES_CLICK, new ArrayList<>(2)); + page.getValue().add(event); + } else { + if (!(tag instanceof CompoundTag)) return false; + event = (CompoundTag) tag; + } + if (!setStringEntry(event, Keys.I_BOOK_PAGES_CLICK_ACTION, Keys.I_BOOK_PAGES_CLICK_ACTION_URL)) + return false; + if (!setStringEntry(event, Keys.I_BOOK_PAGES_CLICK_VALUE, url)) return false; + return true; + } + + @NonNull + public CompoundTag getContent() { + return mContent; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/Keys.java b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/Keys.java new file mode 100644 index 00000000..377ca823 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/Keys.java @@ -0,0 +1,30 @@ +package com.mithrilmania.blocktopograph.nbt; + +public final class Keys { + + public static final String LEVEL_NAME = "LevelName"; + public static final String FLAT_WORLD_LAYERS = "FlatWorldLayers"; + public static final String LAST_PLAYED = "LastPlayed"; + public static final String INVENTORY = "Inventory"; + public static final String INV_NAME = "Name"; + public static final String INV_ID = "id"; + public static final String INV_DAMAGE = "Damage"; + public static final String INV_COUNT = "Count"; + public static final String INV_SLOT = "Slot"; + public static final String INV_TAG = "tag"; + public static final String I_BOOK_AUTHOR = "author"; + public static final String I_BOOK_GENERATION = "generation"; + public static final String I_BOOK_ID = "id"; + public static final String I_BOOK_PAGES = "pages"; + public static final String I_BOOK_TITLE = "title"; + public static final String I_BOOK_XUID = "xuid"; + public static final String I_BOOK_PAGES_PHOTONAME = "photoname"; + public static final String I_BOOK_PAGES_TEXT = "text"; + public static final String I_BOOK_PAGES_CLICK = "clickEvent"; + public static final String I_BOOK_PAGES_CLICK_ACTION = "action"; + public static final String I_BOOK_PAGES_CLICK_ACTION_URL = "open_url"; + public static final String I_BOOK_PAGES_CLICK_VALUE = "value"; + + //public static final String =""; + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/LevelDataConverter.java b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/LevelDataConverter.java index cb5c6331..7d3d8171 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/LevelDataConverter.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/LevelDataConverter.java @@ -16,6 +16,15 @@ public final class LevelDataConverter { public static final byte[] header = {0x04, 0x00, 0x00, 0x00}; + public static CompoundTag read(InputStream inputStream) throws IOException { + skip(inputStream, 8); + // Skip the length? Yeah I know it's redundant but... + NBTInputStream in = new NBTInputStream(inputStream); + CompoundTag levelTag = (CompoundTag) in.readTag(); + in.close(); + return levelTag; + } + public static CompoundTag read(File file) throws IOException { FileInputStream fis = new FileInputStream(file); BufferedInputStream is = new BufferedInputStream(fis); diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/NBTInputStream.java b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/NBTInputStream.java index 937b9894..b4eeb62d 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/NBTInputStream.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/convert/NBTInputStream.java @@ -14,6 +14,8 @@ public final class NBTInputStream private final DataInputStream is; private final boolean littleEndian; + private int readCount; + public NBTInputStream(InputStream is) throws IOException { this(is, false, true); @@ -28,6 +30,7 @@ public NBTInputStream(InputStream is, boolean compressed, boolean littleEndian) throws IOException { this.littleEndian = littleEndian; this.is = new DataInputStream(compressed ? new GZIPInputStream(is) : is); + this.readCount = 0; } public ArrayList readTopLevelTags() { @@ -52,12 +55,15 @@ public Tag readTag() private Tag readTag(int depth) throws IOException { int type = this.is.readByte() & 0xFF; + readCount++; String name; if (type != NBTConstants.NBTType.END.id) { short shLen = this.is.readShort(); + readCount += 2; int nameLength = (this.littleEndian ? Short.reverseBytes(shLen) : shLen) & 0xFFFF; byte[] nameBytes = new byte[nameLength]; this.is.readFully(nameBytes); + readCount += nameLength; name = new String(nameBytes, NBTConstants.CHARSET.name()); } else { name = ""; @@ -70,7 +76,7 @@ private Tag readTagPayload(int type, String name, int depth) NBTConstants.NBTType nbtType = NBTConstants.NBTType.typesByID.get(type); - if(nbtType == null) throw new IOException("Invalid tag type: " + type + "."); + if (nbtType == null) throw new IOException("Invalid tag type: " + type + "."); int length; byte[] bytes; @@ -81,35 +87,47 @@ private Tag readTagPayload(int type, String name, int depth) } return new EndTag(); case BYTE: + readCount++; return new ByteTag(name, this.is.readByte()); case SHORT: + readCount += 2; return new ShortTag(name, this.littleEndian ? Short.reverseBytes(this.is.readShort()) : this.is.readShort()); case INT: + readCount += 4; return new IntTag(name, this.littleEndian ? Integer.reverseBytes(this.is.readInt()) : this.is.readInt()); case LONG: + readCount += 8; return new LongTag(name, this.littleEndian ? Long.reverseBytes(this.is.readLong()) : this.is.readLong()); case FLOAT: + readCount += 4; return new FloatTag(name, this.littleEndian ? Float.intBitsToFloat(Integer.reverseBytes(this.is.readInt())) : this.is.readFloat()); case DOUBLE: + readCount += 8; return new DoubleTag(name, this.littleEndian ? Double.longBitsToDouble(Long.reverseBytes(this.is.readLong())) : this.is.readDouble()); case BYTE_ARRAY: { length = this.littleEndian ? Integer.reverseBytes(this.is.readInt()) : this.is.readInt(); + readCount += 4; bytes = new byte[length]; this.is.readFully(bytes); + readCount += length; return new ByteArrayTag(name, bytes); } case STRING: { length = this.littleEndian ? Short.reverseBytes(this.is.readShort()) : this.is.readShort(); + readCount+=2; bytes = new byte[length]; this.is.readFully(bytes); + readCount += length; return new StringTag(name, new String(bytes, NBTConstants.CHARSET.name())); } case LIST: { int childType = this.is.readByte(); + readCount++; length = this.littleEndian ? Integer.reverseBytes(this.is.readInt()) : this.is.readInt(); + readCount += 4; NBTConstants.NBTType childNbtType = NBTConstants.NBTType.typesByID.get(childType); - if(childNbtType.id == 0) return new ListTag(name, new ArrayList()); + if (childNbtType.id == 0) return new ListTag(name, new ArrayList()); Class clazz = childNbtType.tagClazz; ArrayList tagList = new ArrayList<>(); for (int i = 0; i < length; i++) { @@ -134,26 +152,32 @@ private Tag readTagPayload(int type, String name, int depth) } case INT_ARRAY: { length = this.littleEndian ? Integer.reverseBytes(this.is.readInt()) : this.is.readInt(); + readCount += 4; int[] ints = new int[length]; - if(this.littleEndian) for (int i = 0; i < length; i++) { + readCount += length << 2; + if (this.littleEndian) for (int i = 0; i < length; i++) { ints[i] = Integer.reverseBytes(this.is.readInt()); - } else for (int i = 0; i < length; i++) { + } + else for (int i = 0; i < length; i++) { ints[i] = this.is.readInt(); } return new IntArrayTag(name, ints); } case SHORT_ARRAY: { length = this.littleEndian ? Integer.reverseBytes(this.is.readInt()) : this.is.readInt(); + readCount += 4; short[] shorts = new short[length]; - if(this.littleEndian) for (int i = 0; i < length; i++) { + readCount += length << 1; + if (this.littleEndian) for (int i = 0; i < length; i++) { shorts[i] = Short.reverseBytes(this.is.readShort()); - } else for (int i = 0; i < length; i++) { + } + else for (int i = 0; i < length; i++) { shorts[i] = this.is.readShort(); } return new ShortArrayTag(name, shorts); } default: { - throw new IOException("Unhandled NBT type!!! type: "+type); + throw new IOException("Unhandled NBT type!!! type: " + type); } } } @@ -163,6 +187,14 @@ public void close() this.is.close(); } + public int getReadCount() { + return readCount; + } + + public void resetReadCount() { + readCount = 0; + } + public boolean isLittleEndian() { return this.littleEndian; } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/tags/Tag.java b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/tags/Tag.java index f06823d2..664c7314 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/nbt/tags/Tag.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/nbt/tags/Tag.java @@ -1,8 +1,13 @@ package com.mithrilmania.blocktopograph.nbt.tags; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; import java.io.Serializable; +import java.util.Arrays; +import java.util.List; public abstract class Tag implements Serializable { @@ -29,26 +34,72 @@ public void setName(String name) { this.name = name; } - public T getValue(){ - return value; + private static boolean areCompoundTagsEqual(@NonNull List tags1, @NonNull List tags2) { + if (tags1.size() != tags2.size()) return false; + boolean[] notCompared = new boolean[tags2.size()]; + for (Tag tagof1 : tags1) { + boolean found = false; + for (int i = 0; i < tags2.size(); i++) + if (!notCompared[i] && tagof1.equals(tags2.get(i))) { + found = true; + notCompared[i] = true; + break; + } + if (!found) return false; + } + return true; } - public void setValue(T value){ - this.value = value; + public T getValue() { + return value; } public abstract NBTConstants.NBTType getType(); public abstract Tag getDeepCopy(); - public String toString(){ + public void setValue(T value) { + this.value = value; + } + + public String toString() { String name = getName(); String type = getType().name(); T value = getValue(); - return (type == null ? "?" : ("TAG_"+type)) - + (name == null ? "(?)" : ("("+name+")")) - + (value == null ? ":?" : (": "+value.toString())); + return (type == null ? "?" : ("TAG_" + type)) + + (name == null ? "(?)" : ("(" + name + ")")) + + (value == null ? ":?" : (": " + value.toString())); } - + @Override + public boolean equals(@Nullable Object obj) { + if (!(obj instanceof Tag)) return false; + Tag another = (Tag) obj; + if (!name.equals(another.name)) return false; + if (getType() != another.getType()) return false; + switch (getType()) { + case COMPOUND: + return areCompoundTagsEqual(((CompoundTag) this).value, + ((CompoundTag) another).value); + case INT: + case BYTE: + case LONG: + case FLOAT: + case SHORT: + case DOUBLE: + case STRING: + case LIST: + return value.equals(another.value); + case END: + return true; + case INT_ARRAY: + return Arrays.equals(((IntArrayTag) this).value, ((IntArrayTag) another).value); + case BYTE_ARRAY: + return Arrays.equals(((ByteArrayTag) this).value, ((ByteArrayTag) another).value); + case SHORT_ARRAY: + return Arrays.equals(((ShortArrayTag) this).value, ((ShortArrayTag) another).value); + default: + throw new RuntimeException("wtf????"); + } + } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/test/MainTestActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/test/MainTestActivity.java new file mode 100644 index 00000000..51f0acc2 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/test/MainTestActivity.java @@ -0,0 +1,522 @@ +package com.mithrilmania.blocktopograph.test; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.view.View; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.databinding.DataBindingUtil; + +import com.google.android.material.snackbar.Snackbar; +import com.litl.leveldb.DB; +import com.litl.leveldb.Iterator; +import com.mithrilmania.blocktopograph.Log; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.World; +import com.mithrilmania.blocktopograph.WorldData; +import com.mithrilmania.blocktopograph.block.OldBlock; +import com.mithrilmania.blocktopograph.block.OldBlockRegistry; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.chunk.Chunk; +import com.mithrilmania.blocktopograph.chunk.ChunkTag; +import com.mithrilmania.blocktopograph.chunk.Version; +import com.mithrilmania.blocktopograph.databinding.ActivityMainTestBinding; +import com.mithrilmania.blocktopograph.map.Dimension; +import com.mithrilmania.blocktopograph.nbt.convert.NBTConstants; +import com.mithrilmania.blocktopograph.util.ConvertUtil; +import com.mithrilmania.blocktopograph.util.IoUtil; +import com.mithrilmania.blocktopograph.util.McUtil; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import java.io.File; +import java.io.PrintWriter; +import java.io.Serializable; +import java.io.StringWriter; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +public final class MainTestActivity extends AppCompatActivity { + + private ActivityMainTestBinding mBinding; + private World mWorld; + + /** + * https://stackoverflow.com/a/25659067/9399618 + * + * @param data 123 + * @param pattern 123 + * @return 123 + */ + public static boolean arrContains(byte[] data, byte[] pattern, int[] failure) { + + int j = 0; + + for (byte datum : data) { + while (j > 0 && pattern[j] != datum) { + j = failure[j - 1]; + } + if (pattern[j] == datum) { + j++; + } + if (j == pattern.length) { + return true;//i - pattern.length + 1; + } + } + return false;//-1; + } + + /** + * Computes the failure function using a boot-strapping process, + * where the pattern is matched against itself. + */ + private static int[] computeFailure(byte[] pattern) { + int[] failure = new int[pattern.length]; + + int j = 0; + for (int i = 1; i < pattern.length; i++) { + while (j > 0 && pattern[j] != pattern[i]) { + j = failure[j - 1]; + } + if (pattern[j] == pattern[i]) { + j++; + } + failure[i] = j; + } + + return failure; + } + + private byte[] getDbKey() { + byte[] key; + String text = mBinding.searchBar.getText().toString(); + switch (mBinding.rgForm.getCheckedRadioButtonId()) { + case R.id.rb_form_text: + key = text.getBytes(NBTConstants.CHARSET); + break; + case R.id.rb_form_hex: { + key = ConvertUtil.hexStringToBytes(text); + break; + } + default: + key = null; + } + return key; + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main_test); + + if (savedInstanceState != null) { + Serializable ser = savedInstanceState.getSerializable(World.ARG_WORLD_SERIALIZED); + if (ser instanceof World) mWorld = (World) ser; + } + if (mWorld == null) { + Intent intent = getIntent(); + if (intent != null) { + Serializable ser = intent.getSerializableExtra(World.ARG_WORLD_SERIALIZED); + if (ser instanceof World) mWorld = (World) ser; + } + if (mWorld == null) { + finish(); + return; + } + } + + try { + mWorld.getWorldData().load(); + } catch (WorldData.WorldDataLoadException e) { + Log.d(this, e); + finish(); + return; + } + File file = Environment.getExternalStorageDirectory(); + file = McUtil.getBtgTestDir(file); + mBinding.fabMenuFixLdb.setOnClickListener(this::onClickFixLdb); + //mBinding.fabMenuGenerateAllBlocks.setOnClickListener(this::onClickGenAllBlocks); + //mBinding.fabMenuAnalyzeAllBlocks.setOnClickListener(this::onClickAnaAllBlocks); + //mBinding.fabMenuGenCodeAllBlocksState.setOnClickListener(this::onClickGenCodeAllBlocksState); + mBinding.setPath(file.getPath()); + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable(World.ARG_WORLD_SERIALIZED, mWorld); + } + + private byte[] readItem() { + return readItem(getDbKey()); + } + + private byte[] readItem(byte[] key) { + byte[] ret; + WorldData wdata = mWorld.getWorldData(); + try { + wdata.openDB(); + ret = wdata.db.get(key); + wdata.closeDB(); + } catch (Exception e) { + Log.d(this, e); + ret = null; + } + try { + wdata.closeDB(); + } catch (WorldData.WorldDBException e) { + Log.d(this, e); + } + return ret; + } + + public void onClickSearch(View view) { + byte[] pattern = getDbKey(); + WorldData wdata = mWorld.getWorldData(); + try { + wdata.openDB(); + List keys = new ArrayList<>(); + List keyTypeText = new ArrayList<>(); + List originalKeys = new ArrayList<>(); + Iterator iter = wdata.db.iterator(); + int[] failure = computeFailure(pattern); + for (iter.seekToFirst(); iter.isValid(); iter.next()) { + byte[] key = iter.getKey(); + if (arrContains(key, pattern, failure)) { + String str = null; + boolean isText = false; + if (mBinding.rgForm.getCheckedRadioButtonId() == R.id.rb_form_text) { + try { + str = new String(key, NBTConstants.CHARSET); + isText = true; + } catch (Exception ignored) { + } + } + if (str == null) + str = ConvertUtil.bytesToHexStr(key); + keys.add(str); + originalKeys.add(key); + keyTypeText.add(isText); + } + } + iter.close(); + wdata.closeDB(); + String[] keyArr = new String[keys.size()]; + keys.toArray(keyArr); + AlertDialog dia = new AlertDialog.Builder(this).setItems(keyArr, (di, i) -> { + mBinding.searchBar.setText(keyArr[i]); + if (keyTypeText.get(i)) + mBinding.rbFormText.setChecked(true); + else + mBinding.rbFormHex.setChecked(true); + showData(readItem(originalKeys.get(i))); + }).create(); + dia.show(); + } catch (Exception e) { + Log.d(this, e); + printStackTraceInDialog(e); + } + try { + wdata.closeDB(); + } catch (WorldData.WorldDBException e) { + Log.d(this, e); + } + } + + private void showData(byte[] data) { + new AlertDialog.Builder(this) + .setMessage(ConvertUtil.bytesToHexStr(data)) + .show(); + } + + private void printStackTraceInDialog(Exception e) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + pw.close(); + new AlertDialog.Builder(this).setMessage(sw.toString()).create().show(); + } + + public void onClickOpen(View view) { + showData(readItem()); + } + + public void onClickExport(View view) { + IoUtil.Errno errno; + flow: + { + + byte[] item = readItem(); + + if (!IoUtil.hasWritePermission(this)) { + errno = IoUtil.Errno.PERMISSION_DENIED; + break flow; + } + + File dir = new File(mBinding.textPath.getText().toString()); + + errno = IoUtil.makeSureDirIsDir(dir); + if (IoUtil.Errno.OK != errno) { + break flow; + } + + String name = ConvertUtil.getLegalFileName(mBinding.searchBar.getText().toString()); + File out = IoUtil.getFileWithFirstAvailableName(dir, name, ".dat", "(", ")"); + if (out == null) { + errno = IoUtil.Errno.UNKNOWN; + break flow; + } + + if (!IoUtil.writeBinaryFile(out, item)) errno = IoUtil.Errno.UNKNOWN; + } + if (errno == IoUtil.Errno.OK) Snackbar.make(getWindow().getDecorView(), + R.string.general_done, Snackbar.LENGTH_SHORT).show(); + else Toast.makeText(this, errno.toString(), Toast.LENGTH_SHORT).show(); + } + + @SuppressWarnings("unchecked") + private void onClickFixLdb(View view) { + new ForegroundTask(this).execute(() -> { + WorldData worldData = mWorld.getWorldData(); + try { + worldData.closeDB(); + } catch (WorldData.WorldDBException e) { + Log.d(this, e); + } + return DB.fixLdb(worldData.db.getPath().getAbsolutePath()); + }); + } + + /*@SuppressWarnings("unchecked") + private void onClickGenAllBlocks(View view) { + new ForegroundTask(this).execute(() -> { + WorldData worldData = mWorld.getWorldData(); + OldBlockRegistry registry = worldData.mOldBlockRegistry; + int pos = 0; + for (KnownBlockRepr oldBlock : KnownBlockRepr.values()) { + if (pos % 16 == 0) + worldData.removeChunkData(pos / 16, 0, ChunkTag.TERRAIN, Dimension.OVERWORLD, (byte) 0, true); + String pot = "------------X------------" + + "------XXX--XOX--XXX------" + + "XXXXXX---XX-?-XX---XXXXXX"; + Chunk chunk = worldData.getChunk(pos / 16, 0, Dimension.OVERWORLD, true, Version.V1_2_PLUS); + int i = 0; + for (int y = 0; y < 3; y++) + for (int x = 0; x < 5; x++) + for (int z = 0; z < 5; z++) { + OldBlock blk; + switch (pot.charAt(i)) { + case 'X': + blk = registry.createBlock(KnownBlockRepr.B_42_0_IRON_BLOCK); + break; + case 'O': + blk = registry.createBlock(KnownBlockRepr.B_3_0_DIRT); + break; + case '?': + blk = registry.createBlock(oldBlock); + break; + default: + blk = null; + } + if (blk != null) + chunk.setBlock(pos % 16 + 1 + x, 12 + y, 3 + z, 0, blk); + i++; + } + for (int j = 0; j < 8; j++) { + chunk.setBlock(pos % 16 + j, 17, 9, 0, + registry.createBlock(KnownBlockRepr.B_12_0_SAND_DEFAULT)); + chunk.setBlock(pos % 16 + j, 0, 9, 0, + registry.createBlock(KnownBlockRepr.B_42_0_IRON_BLOCK)); + } + pos += 8; + } + worldData.resetCache(); + worldData.closeDB(); + return "meow"; + }); + }*/ + + @SuppressWarnings("unchecked") + private void onClickAnaAllBlocks(View view) { +// new ForegroundTask(this).execute(() -> { +// WorldData worldData = mWorld.getWorldData(); +// int pos = 0, valids = 0, invalids = 0, offs = 0; +// StringBuilder sb = new StringBuilder(); +// CompoundTag[] tags = null; +// for (KnownBlockRepr oldBlock : KnownBlockRepr.values()) { +// Chunk chunk = worldData.getChunk(pos / 16, 0, Dimension.OVERWORLD, true, Version.V1_2_PLUS); +// int ind; +// if (pos % 16 == 0) { +// tags = ((BedrockChunk) chunk).tempGetSubChunk().tempGetPalettes(3, 14, 5); +// ind = 0; +// } else ind = 1; +// String name = ((StringTag) tags[ind].getChildTagByKey("name")).getValue().substring(10); +// sb.append(oldBlock.identifier).append(":").append(oldBlock.subId).append("->").append(name).append(":"); +// CompoundTag states = ((CompoundTag) tags[ind].getChildTagByKey("states")); +// sb.append("["); +// ArrayList value = states.getValue(); +// for (int i = 0; i < value.size(); i++) { +// Tag tag = value.get(i); +// sb.append(tag.getType()).append(":").append(tag.getIdentifier()).append("="); +// switch (tag.getType()) { +// case INT: +// sb.append(((IntTag) tag).getValue()); +// break; +// case BYTE: +// sb.append(((ByteTag) tag).getValue()); +// break; +// case SHORT: +// sb.append(((ShortTag) tag).getValue()); +// break; +// case STRING: +// sb.append(((StringTag) tag).getValue()); +// break; +// } +// if (i != value.size() - 1) sb.append(","); +// } +// sb.append("]\n"); +// pos += 8; +// offs++; +// } +// worldData.resetCache(); +// worldData.closeDB(); +// IoUtil.writeTextFile(new File(McUtil.getBtgTestDir(Environment.getExternalStorageDirectory()), "blks.txt"), sb.toString()); +// return "meow"; +// }); + } + + @SuppressWarnings("unchecked") + private void onClickGenCodeAllBlocksState(View view) { +// new ForegroundTask(this).execute(() -> { +// WorldData worldData = mWorld.getWorldData(); +// int pos = 0, valids = 0, invalids = 0; +// StringBuilder sb = new StringBuilder(); +// CompoundTag[] tags = null; +// for (KnownBlockRepr oldBlock : KnownBlockRepr.values()) { +// Chunk chunk = worldData.getChunk(pos / 16, 0, Dimension.OVERWORLD, true, Version.V1_2_PLUS); +// int ind; +// if (pos % 16 == 0) { +// tags = ((BedrockChunk) chunk).tempGetSubChunk().tempGetPalettes(3, 14, 5); +// ind = 0; +// } else ind = 1; +// String name = ((StringTag) tags[ind].getChildTagByKey("name")).getValue().substring(10); +// if (name.equals(oldBlock.identifier)) { +// CompoundTag states = ((CompoundTag) tags[ind].getChildTagByKey("states")); +// sb.append("new BlockStateBuilder()"); +// Object[] value = states.getValue().toArray(); +// Arrays.sort(value, (o1, o2) -> { +// String n1 = ((Tag) o1).getIdentifier(); +// String n2 = ((Tag) o2).getIdentifier(); +// if (n1.contains("color")) +// return -1; +// if (n2.contains("color")) +// return 1; +// if (n1.contains("type")) +// return -1; +// if (n2.contains("type")) +// return 1; +// if (n1.contains("direction")) +// return -1; +// if (n2.contains("direction")) +// return 1; +// return 0; +// }); +// for (int i = 0; i < value.length; i++) { +// Tag tag = (Tag) value[i]; +// String tagName = tag.getIdentifier(); +// switch (tag.getType()) { +// case INT: +// sb.append(".addInt(\"").append(tagName).append("\", "); +// sb.append(((IntTag) tag).getValue()); +// break; +// case BYTE: +// sb.append(".addByte(\"").append(tagName).append("\", (byte)"); +// sb.append(((ByteTag) tag).getValue()); +// break; +// case SHORT: +// sb.append(".addShort(\"").append(tagName).append("\", (short)"); +// sb.append(((ShortTag) tag).getValue()); +// break; +// case STRING: +// sb.append(".addProperty(\"").append(tagName).append("\", \""); +// sb.append(((StringTag) tag).getValue()).append("\""); +// break; +// } +// sb.append(")"); +// } +// sb.append(".build()\n"); +// valids++; +// } else { +// sb.append("new CompoundTag(\"\", new ArrayList())\n"); +// invalids++; +// } +// pos += 8; +// } +// worldData.resetCache(); +// worldData.closeDB(); +// IoUtil.writeTextFile(new File(McUtil.getBtgTestDir(Environment.getExternalStorageDirectory()), "blkStateCodes.txt"), sb.toString()); +// return "meow valids: " + valids + ", invalids: " + invalids; +// }); + } + + private static class ForegroundTask extends AsyncTask, Void, Void> { + + private WeakReference mContext; + private WeakReference

mDialog; + private StringBuilder result; + + ForegroundTask(Context context) { + mContext = new WeakReference<>(context); + result = new StringBuilder(); + } + + @Override + protected void onPreExecute() { + Context context = mContext.get(); + if (context == null) return; + AlertDialog dialog = UiUtil.buildProgressWaitDialog(context, R.string.general_please_wait, null); + dialog.show(); + mDialog = new WeakReference<>(dialog); + } + + @SafeVarargs + @Override + protected final Void doInBackground(Callable... params) { + for (Callable callable : params) { + try { + result.append(callable.call()); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + Dialog dialog; + if (mDialog != null && (dialog = mDialog.get()) != null) { + try { + dialog.dismiss(); + } catch (Exception e) { + Log.e(this, e); + } + } + Context context = mContext.get(); + if (context != null) { + new AlertDialog.Builder(context) + .setMessage(result.toString()) + .create().show(); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/test/VisualizationActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/test/VisualizationActivity.java new file mode 100644 index 00000000..ddb88561 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/test/VisualizationActivity.java @@ -0,0 +1,6 @@ +package com.mithrilmania.blocktopograph.test; + +import androidx.appcompat.app.AppCompatActivity; + +public class VisualizationActivity extends AppCompatActivity { +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/Color.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/Color.java deleted file mode 100644 index 8b3b701c..00000000 --- a/app/src/main/java/com/mithrilmania/blocktopograph/util/Color.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.mithrilmania.blocktopograph.util; - - -public class Color { - - private static final int BIT_MASK = 0xff; - - public final int alpha; - - public final int red; - public final int green; - public final int blue; - - /** - * Creates a new Color object from a red, green, and blue - * - * @param red integer from 0-255 - * @param green integer from 0-255 - * @param blue integer from 0-255 - * @return a new Color object for the red, green, blue - * @throws IllegalArgumentException if any value is strictly >255 or <0 - */ - public static Color fromRGB(int red, int green, int blue) throws IllegalArgumentException { - return new Color(0xff, red, green, blue); - } - - /** - * Creates a new color object from an integer that contains the red, green, and blue bytes in the lowest order 24 bits. - * - * @param rgb the integer storing the red, green, and blue values - * @return a new color object for specified values - * @throws IllegalArgumentException if any data is in the highest order 8 bits - */ - public static Color fromRGB(int rgb) throws IllegalArgumentException { - return fromRGB(rgb >> 16 & BIT_MASK, rgb >> 8 & BIT_MASK, rgb & BIT_MASK); - } - - public static Color fromARGB(int alpha, int red, int green, int blue) throws IllegalArgumentException { - return new Color(alpha, red, green, blue); - } - - public static Color fromARGB(int argb) throws IllegalArgumentException { - return fromARGB(argb >> 24 & BIT_MASK, argb >> 16 & BIT_MASK, argb >> 8 & BIT_MASK, argb & BIT_MASK); - } - - public Color(int alpha, int red, int green, int blue) { - this.alpha = alpha; - this.red = red; - this.green = green; - this.blue = blue; - } - - /** - * - * @return An integer representation of this color, as 0xRRGGBB - */ - public int asRGB() { - return red << 16 | green << 8 | blue; - } - - public int asARGB() { - return alpha << 24 | red << 16 | green << 8 | blue; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Color)) { - return false; - } - final Color that = (Color) o; - return this.alpha == that.alpha && this.red == that.red && this.green == that.green && this.blue == that.blue; - } - - @Override - public int hashCode() { - return asRGB() ^ Color.class.hashCode(); - } - - - @Override - public String toString() { - return "Color:[argb0x" - + Integer.toHexString(alpha).toUpperCase() - + Integer.toHexString(red).toUpperCase() - + Integer.toHexString(green).toUpperCase() - + Integer.toHexString(blue).toUpperCase() - + "]"; - } -} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/ColorUtil.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/ColorUtil.java new file mode 100644 index 00000000..26ad2919 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/ColorUtil.java @@ -0,0 +1,25 @@ +package com.mithrilmania.blocktopograph.util; + +import android.graphics.Color; + +public class ColorUtil { + public static int truncateArgb(int a, int r, int g, int b) { + return Color.argb(ensureColorRange(a), + ensureColorRange(r), ensureColorRange(g), ensureColorRange(b) + ); + } + + public static int truncateRgb(int r, int g, int b) { + return Color.rgb( + ensureColorRange(r), ensureColorRange(g), ensureColorRange(b) + ); + } + + private static int ensureRange(int val, int min, int max) { + return Math.min(Math.max(val, min), max); + } + + private static int ensureColorRange(int val) { + return ensureRange(val, 0, 255); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/ColorWrapper.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/ColorWrapper.java new file mode 100644 index 00000000..cd7ba664 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/ColorWrapper.java @@ -0,0 +1,91 @@ +package com.mithrilmania.blocktopograph.util; + + +import androidx.annotation.NonNull; + +public class ColorWrapper { + + private static final int BIT_MASK = 0xff; + + public final int alpha; + + public final int red; + public final int green; + public final int blue; + + public ColorWrapper(int alpha, int red, int green, int blue) { + this.alpha = alpha; + this.red = red; + this.green = green; + this.blue = blue; + } + + /** + * Creates a new ColorWrapper object from a red, green, and blue + * + * @param red integer from 0-255 + * @param green integer from 0-255 + * @param blue integer from 0-255 + * @return a new ColorWrapper object for the red, green, blue + * @throws IllegalArgumentException if any value is strictly >255 or <0 + */ + public static ColorWrapper fromRGB(int red, int green, int blue) throws IllegalArgumentException { + return new ColorWrapper(0xff, red, green, blue); + } + + /** + * Creates a new color object from an integer that contains the red, green, and blue bytes in the lowest order 24 bits. + * + * @param rgb the integer storing the red, green, and blue values + * @return a new color object for specified values + * @throws IllegalArgumentException if any data is in the highest order 8 bits + */ + public static ColorWrapper fromRGB(int rgb) throws IllegalArgumentException { + return fromRGB(rgb >> 16 & BIT_MASK, rgb >> 8 & BIT_MASK, rgb & BIT_MASK); + } + + public static ColorWrapper fromARGB(int alpha, int red, int green, int blue) throws IllegalArgumentException { + return new ColorWrapper(alpha, red, green, blue); + } + + public static ColorWrapper fromARGB(int argb) throws IllegalArgumentException { + return fromARGB(argb >> 24 & BIT_MASK, argb >> 16 & BIT_MASK, argb >> 8 & BIT_MASK, argb & BIT_MASK); + } + + /** + * @return An integer representation of this color, as 0xRRGGBB + */ + public int asRGB() { + return red << 16 | green << 8 | blue; + } + + public int asARGB() { + return alpha << 24 | red << 16 | green << 8 | blue; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ColorWrapper)) { + return false; + } + final ColorWrapper that = (ColorWrapper) o; + return this.alpha == that.alpha && this.red == that.red && this.green == that.green && this.blue == that.blue; + } + + @Override + public int hashCode() { + return asRGB() ^ ColorWrapper.class.hashCode(); + } + + + @NonNull + @Override + public String toString() { + return "ColorWrapper:[argb0x" + + Integer.toHexString(alpha) + + Integer.toHexString(red) + + Integer.toHexString(green) + + Integer.toHexString(blue) + + "]"; + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/Consumer.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/Consumer.java new file mode 100644 index 00000000..6f9061f5 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/Consumer.java @@ -0,0 +1,7 @@ +package com.mithrilmania.blocktopograph.util; + +@FunctionalInterface +public interface Consumer { + + void accept(T param); +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/ConvertUtil.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/ConvertUtil.java index 18dabd50..7fe70928 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/util/ConvertUtil.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/ConvertUtil.java @@ -1,18 +1,133 @@ package com.mithrilmania.blocktopograph.util; + + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * Convert utils */ public class ConvertUtil { public static String bytesToHexStr(byte[] in) { - if(in == null) return "null"; + if (in == null) return "null"; final StringBuilder builder = new StringBuilder(); - for(byte b : in) { + for (byte b : in) { builder.append(String.format("%02x", b)); } return builder.toString(); } + private static int hexCharToByte(char ch) { + switch (ch) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'a': + return 10; + case 'b': + return 11; + case 'c': + return 12; + case 'd': + return 13; + case 'e': + return 14; + case 'f': + return 15; + case 'A': + return 10; + case 'B': + return 11; + case 'C': + return 12; + case 'D': + return 13; + case 'E': + return 14; + case 'F': + return 15; + default: + return -1; + } + } + + @Nullable + public static byte[] hexStringToBytes(@NonNull String text) { + byte[] ret; + if (text.charAt(0) == '0' && (text.charAt(1) == 'x' || text.charAt(1) == 'X')) + text = text.substring(2); + flow: + { + int len = text.length(); + if ((len & 1) != 0) { + ret = null; + break flow; + } + len = len >> 1; + ret = new byte[len]; + for (int i = 0; i < len; i++) { + int h = hexCharToByte(text.charAt(i << 1)) << 4; + if (h < 0) break flow; + int l = hexCharToByte(text.charAt(i << 1 | 1)); + if (l < 0) break flow; + ret[i] = (byte) (h | l); + } + } + return ret; + } + + @NonNull + public static String getLegalFileName(@NonNull String text) { + return text.replaceAll("[\\\\/:*?\"<>|.]", "_"); + } + + @Nullable + public static String guessPictureMimeFromExtension(@NonNull String extension, boolean inLower) { + // assert extension.length()>0; + if (extension.charAt(0) == '.') extension = extension.substring(1); + if (!inLower) extension = extension.toLowerCase(); + String MIME_PNG = "image/png"; + String MIME_JPG = "image/jpg"; + switch (extension) { + case "png": + return MIME_PNG; + case "jpg": + case "jpeg": + return MIME_JPG; + default: + return null; + } + } + + public static float distance(float x1, float y1, float x2, float y2) { + float d1 = x2 - x1; + float d2 = y2 - y1; + return (float) Math.sqrt(d1 * d1 + d2 * d2); + } + + public static double distance(double x1, double y1, double x2, double y2) { + double d1 = x2 - x1; + double d2 = y2 - y1; + return Math.sqrt(d1 * d1 + d2 * d2); + } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/IoUtil.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/IoUtil.java new file mode 100644 index 00000000..9476a9c6 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/IoUtil.java @@ -0,0 +1,251 @@ +package com.mithrilmania.blocktopograph.util; + + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.res.AssetManager; +import android.graphics.Bitmap; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; + +import com.mithrilmania.blocktopograph.Log; + +import org.apache.commons.io.FileUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; + +public class IoUtil { + + /** + * Extract file from app asset to file system. + * + * @param mgr Asset manager instance. + * @param name Asset path. No slash at beginning or end. + * @param mode Asset access mode used in AssetManager.open(). + * @param out Output file path. Shall be accessible. + * @return Success or not. + */ + public static boolean extractAsset(AssetManager mgr, String name, int mode, File out) { + InputStream is = null; + FileOutputStream fos = null; + boolean ret = false; + try { + is = mgr.open(name, AssetManager.ACCESS_BUFFER); + fos = new FileOutputStream(out); + //FileUtil.copyStream(is, fos); + ret = true; + } catch (Exception e) { + e.printStackTrace(); + } + try { + if (is != null) is.close(); + } catch (Exception ignored) { + } + try { + if (fos != null) fos.close(); + } catch (Exception ignored) { + } + return ret; + } + + /** + * Read first line of a text file. Designed for levelname.txt. + * + * @param txtFile File to be read. + * @return Read content. Null if failed. + */ + public static String readTextFileFirstLine(File txtFile) { + String text = null; + BufferedReader br; + try { + br = new BufferedReader(new FileReader(txtFile)); + text = br.readLine(); + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return text; + } + + /** + * Make sure a certain directory exists and is a directory instead of other types of file. + *

+ * Will create the directory if not exist. + *

+ * + * @param dir Directory to be verified or created. + * @return Whether it's verified or failed for a reason. + */ + public static Errno makeSureDirIsDir(@NonNull File dir) { + if (dir.exists()) { + if (!dir.isDirectory()) return Errno.FILE_WITH_SAME_NAME_EXISTS; + } else { + if (!dir.mkdirs()) return Errno.CANNOT_MKDIRS; + } + return Errno.OK; + } + + /** + * Given a target file, add some variation to avoid name conflicts with existing file. + *

+ * For instance "/sdcard/xxx/meow.txt" may be a wanted name, + * but there exist "meow.txt", "meow (1).txt" and then + * "meow (2).txt have to be used. + *

+ * + * @param parent Directory the target file would reside. + * @param lhalf Left half of file name. E.g. "meow" for "meow ($count).txt". + * @param rhalf Right half of file name. E.g. ".txt" for "meow ($count).txt". + * @param prefix Prefix for the dynamic part. E.g. "(" for "meow ($count).txt". + * @param suffix Suffix for the dynamic part. E.g. ")" for "meow ($count).txt". + * @return The available name, or null if failed too many times. + */ + @Nullable + public static File getFileWithFirstAvailableName(@NonNull File parent, @NonNull String + lhalf, + @NonNull String rhalf, @NonNull String prefix, + @NonNull String suffix) { + StringBuilder sb = new StringBuilder(); + sb.append(lhalf).append(rhalf); + File target = new File(parent, sb.toString()); + if (!target.exists()) return target; + int count = 0; + do { + count++; + if (count > 999) return null; + sb = new StringBuilder(256).append(lhalf).append(prefix) + .append(count).append(suffix).append(rhalf); + target = new File(parent, sb.toString()); + } while (target.exists()); + return target; + } + + public static boolean writeTextFile(@NonNull File file, @NonNull String name) { + try { + FileUtils.writeStringToFile(file, name); + return true; + } catch (IOException ignored) { + return false; + } + } + + public static boolean writeBinaryFile(@NonNull File file, @NonNull byte[] data) { + try { + FileUtils.writeByteArrayToFile(file, data); + return true; + } catch (IOException e) { + return false; + } + } + + /** + * Simple helper function to get the size of a folder or file in text format, + * + * @param size size + * @return size, formatted with a "B", "MB, "GB" or "TB", precise to 2 decimals. + */ + @NonNull + public static String getFileSizeInText(long size) { + if (size < 1024) return size + " B"; + double v = size / 1024.0; + String suffix = "KB"; + if (v > 1024.0) { + v /= 1024.0; + if (v > 1024.0) { + v /= 1024.0; + if (v > 1024.0) { + v /= 1024.0; + suffix = "TB";//very high end android device here + } else suffix = "GB"; + } else suffix = "MB"; + } + + return String.format(Locale.ENGLISH, "%.2f %s", v, suffix); + + } + + public enum Errno { + OK, FILE_WITH_SAME_NAME_EXISTS, CANNOT_MKDIRS, + PERMISSION_DENIED, UNKNOWN + } + + /** + * Check if app has storage write permission. Use after requested permission in a previous activity. + * + * @param context Context. + * @return True if has permission, otherwise false. + */ + public static boolean hasWritePermission(@NonNull Context context) { + int permission = ActivityCompat.checkSelfPermission( + context, Manifest.permission.WRITE_EXTERNAL_STORAGE); + return permission == PackageManager.PERMISSION_GRANTED; + } + + /** + * Save a bitmap to file using Android's compress methods. + * + * @param bmp bitmap to save. + * @param format format required by Android. Png, Jpeg and Webp supported. + * @param quality Quality if using Jpeg. + * @param dir Directory to save to, should be folder not ordinary file. + * @param baseName Name of the file, without extension. + * @param autoRename Should file be automatically renamed to "xxx (1).jpg" things + * if a conflict happened. + * @return The file the bitmap was saved to, null if failed. + */ + @Nullable + public static File saveBitmap(@NonNull Bitmap bmp, @NonNull Bitmap.CompressFormat format, + int quality, @NonNull File dir, @NonNull String baseName, + boolean autoRename) { + String extension; + if (!dir.exists()) { + if (autoRename) { + // If allowed to auto rename lets assume mkdir's also reasonable. + if (makeSureDirIsDir(dir) != Errno.OK) return null; + } else return null; + } + switch (format) { + case JPEG: + extension = ".jpg"; + break; + case PNG: + extension = ".png"; + break; + case WEBP: + extension = ".webp"; + break; + default: + return null; + } + File saveTo = autoRename ? + getFileWithFirstAvailableName(dir, baseName, extension, "(", ")") + : new File(dir, baseName + extension); + if (saveTo == null) return null; + FileOutputStream fos = null; + try { + fos = new FileOutputStream(saveTo); + bmp.compress(format, quality, fos); + fos.close(); + return saveTo; + } catch (Exception e) { + Log.d(IoUtil.class, e); + if (fos != null) try { + fos.close(); + } catch (Exception ignore) { + } + return null; + } + } + + public static void rubbish() { + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/LittleEndianOutputStream.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/LittleEndianOutputStream.java new file mode 100644 index 00000000..a0fbb8e5 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/LittleEndianOutputStream.java @@ -0,0 +1,296 @@ +/* + * @(#)LittleEndianOutputStream.java 1.0.1 99/05/19 + * + * Copyright 1998, 1999 Elliotte Rusty Harold + * + */ + +package com.mithrilmania.blocktopograph.util; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UTFDataFormatException; + +/** + * A little endian output stream writes primitive Java numbers + * and characters to an output stream in a little endian format. + * The standard java.io.DataOutputStream class which this class + * imitates uses big-endian integers. + * + * @author Elliotte Rusty Harold + * @version 1.0.1, 19 May 1999 + * see com.macfaq.io.LittleEndianInputStream + * @see java.io.DataOutputStream + */ +public class LittleEndianOutputStream extends FilterOutputStream { + + /** + * The number of bytes written so far to the little endian output stream. + */ + protected int written; + + /** + * Creates a new little endian output stream and chains it to the + * output stream specified by the out argument. + * + * @param out the underlying output stream. + * @see java.io.FilterOutputStream#out + */ + public LittleEndianOutputStream(OutputStream out) { + super(out); + } + + /** + * Writes the specified byte value to the underlying output stream. + * + * @param b the byte value to be written. + * @throws IOException if the underlying stream throws an IOException. + */ + public synchronized void write(int b) throws IOException { + out.write(b); + written++; + } + + /** + * Writes length bytes from the specified byte array + * starting at offset to the underlying output stream. + * + * @param data the data. + * @param offset the start offset in the data. + * @param length the number of bytes to write. + * @throws IOException if the underlying stream throws an IOException. + */ + public synchronized void write(byte[] data, int offset, int length) + throws IOException { + out.write(data, offset, length); + written += length; + } + + + /** + * Writes a boolean to the underlying output stream as + * a single byte. If the argument is true, the byte value 1 is written. + * If the argument is false, the byte value 0 in written. + * + * @param b the boolean value to be written. + * @throws IOException if the underlying stream throws an IOException. + */ + public void writeBoolean(boolean b) throws IOException { + + if (b) this.write(1); + else this.write(0); + + } + + /** + * Writes out a byte to the underlying output stream + * + * @param b the byte value to be written. + * @throws IOException if the underlying stream throws an IOException. + */ + public void writeByte(int b) throws IOException { + out.write(b); + written++; + } + + /** + * Writes a two byte short to the underlying output stream in + * little endian order, low byte first. + * + * @param s the short to be written. + * @throws IOException if the underlying stream throws an IOException. + */ + public void writeShort(int s) throws IOException { + + out.write(s & 0xFF); + out.write((s >>> 8) & 0xFF); + written += 2; + + } + + /** + * Writes a two byte char to the underlying output stream + * in little endian order, low byte first. + * + * @param c the char value to be written. + * @throws IOException if the underlying stream throws an IOException. + */ + public void writeChar(int c) throws IOException { + + out.write(c & 0xFF); + out.write((c >>> 8) & 0xFF); + written += 2; + + } + + /** + * Writes a four-byte int to the underlying output stream + * in little endian order, low byte first, high byte last + * + * @param i the int to be written. + * @throws IOException if the underlying stream throws an IOException. + */ + public void writeInt(int i) throws IOException { + + out.write(i & 0xFF); + out.write((i >>> 8) & 0xFF); + out.write((i >>> 16) & 0xFF); + out.write((i >>> 24) & 0xFF); + written += 4; + + } + + /** + * Writes an eight-byte long to the underlying output stream + * in little endian order, low byte first, high byte last + * + * @param l the long to be written. + * @throws IOException if the underlying stream throws an IOException. + */ + public void writeLong(long l) throws IOException { + + out.write((int) l & 0xFF); + out.write((int) (l >>> 8) & 0xFF); + out.write((int) (l >>> 16) & 0xFF); + out.write((int) (l >>> 24) & 0xFF); + out.write((int) (l >>> 32) & 0xFF); + out.write((int) (l >>> 40) & 0xFF); + out.write((int) (l >>> 48) & 0xFF); + out.write((int) (l >>> 56) & 0xFF); + written += 8; + + } + + /** + * Writes a 4 byte Java float to the underlying output stream in + * little endian order. + * + * @param f the float value to be written. + * @throws IOException if an I/O error occurs. + */ + public final void writeFloat(float f) throws IOException { + + this.writeInt(Float.floatToIntBits(f)); + + } + + /** + * Writes an 8 byte Java double to the underlying output stream in + * little endian order. + * + * @param d the double value to be written. + * @throws IOException if an I/O error occurs. + */ + public final void writeDouble(double d) throws IOException { + + this.writeLong(Double.doubleToLongBits(d)); + + } + + /** + * Writes a string to the underlying output stream as a sequence of + * bytes. Each character is written to the data output stream as + * if by the writeByte() method. + * + * @param s the String value to be written. + * @throws IOException if the underlying stream throws an IOException. + * see java.io.LittleEndianOutputStream#writeByte(int) + * see java.io.LittleEndianOutputStream#out + */ + public void writeBytes(String s) throws IOException { + + int length = s.length(); + for (int i = 0; i < length; i++) { + out.write((byte) s.charAt(i)); + } + written += length; + } + + /** + * Writes a string to the underlying output stream as a sequence of + * characters. Each character is written to the data output stream as + * if by the writeChar method. + * + * @param s a String value to be written. + * @throws IOException if the underlying stream throws an IOException. + * see java.io.LittleEndianOutputStream#writeChar(int) + * see java.io.LittleEndianOutputStream#out + */ + public void writeChars(String s) throws IOException { + + int length = s.length(); + for (int i = 0; i < length; i++) { + int c = s.charAt(i); + out.write(c & 0xFF); + out.write((c >>> 8) & 0xFF); + } + written += length * 2; + + } + + /** + * Writes a string of no more than 65,535 characters + * to the underlying output stream using UTF-8 + * encoding. This method first writes a two byte short + * in big endian order as required by the + * UTF-8 specification. This gives the number of bytes in the + * UTF-8 encoded version of the string, not the number of characters + * in the string. Next each character of the string is written + * using the UTF-8 encoding for the character. + * + * @param s the string to be written. + * @throws UTFDataFormatException if the string is longer than + * 65,535 characters. + * @throws IOException if the underlying stream throws an IOException. + */ + public void writeUTF(String s) throws IOException { + + int numchars = s.length(); + int numbytes = 0; + + for (int i = 0; i < numchars; i++) { + int c = s.charAt(i); + if ((c >= 0x0001) && (c <= 0x007F)) numbytes++; + else if (c > 0x07FF) numbytes += 3; + else numbytes += 2; + } + + if (numbytes > 65535) throw new UTFDataFormatException(); + + out.write((numbytes >>> 8) & 0xFF); + out.write(numbytes & 0xFF); + for (int i = 0; i < numchars; i++) { + int c = s.charAt(i); + if ((c >= 0x0001) && (c <= 0x007F)) { + out.write(c); + } else if (c > 0x07FF) { + out.write(0xE0 | ((c >> 12) & 0x0F)); + out.write(0x80 | ((c >> 6) & 0x3F)); + out.write(0x80 | (c & 0x3F)); + written += 2; + } else { + out.write(0xC0 | ((c >> 6) & 0x1F)); + out.write(0x80 | (c & 0x3F)); + written += 1; + } + } + + written += numchars + 2; + + } + + /** + * Returns the number of bytes written to this little endian output stream. + * (This class is not thread-safe with respect to this method. It is + * possible that this number is temporarily less than the actual + * number of bytes written.) + * + * @return the value of the written field. + * see java.io.LittleEndianOutputStream#written + */ + public int size() { + return this.written; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/McUtil.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/McUtil.java new file mode 100644 index 00000000..230d1a2d --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/McUtil.java @@ -0,0 +1,33 @@ +package com.mithrilmania.blocktopograph.util; + +import androidx.annotation.NonNull; + +import java.io.File; + +public final class McUtil { + + @NonNull + + public static File getMinecraftWorldsDir(File sdcard) { + return new File(sdcard, "games/com.mojang/minecraftWorlds"); + } + + @NonNull + + public static File getBtgTestDir(File sdcard) { + return new File(sdcard, "games/com.mojang/btgTest"); + } + + @NonNull + + public static File getLevelDatFile(File world) { + return new File(world, "level.dat"); + } + + @NonNull + + public static File getLevelNameFile(File world) { + return new File(world, "levelname.txt"); + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProvider.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProvider.java index db81645e..be9f5fd6 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProvider.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProvider.java @@ -1,7 +1,7 @@ package com.mithrilmania.blocktopograph.util; import android.graphics.Bitmap; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; public interface NamedBitmapProvider { diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProviderHandle.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProviderHandle.java index 5d4df6db..717dfef0 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProviderHandle.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/NamedBitmapProviderHandle.java @@ -1,6 +1,6 @@ package com.mithrilmania.blocktopograph.util; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; public interface NamedBitmapProviderHandle { diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/UiUtil.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/UiUtil.java new file mode 100644 index 00000000..b070b5d2 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/util/UiUtil.java @@ -0,0 +1,156 @@ +package com.mithrilmania.blocktopograph.util; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.AlertDialog; +import androidx.core.graphics.ColorUtils; +import androidx.databinding.DataBindingUtil; + +import com.google.android.material.snackbar.Snackbar; +import com.mithrilmania.blocktopograph.R; +import com.mithrilmania.blocktopograph.block.BlockTemplate; +import com.mithrilmania.blocktopograph.block.KnownBlockRepr; +import com.mithrilmania.blocktopograph.block.ListingBlock; +import com.mithrilmania.blocktopograph.databinding.GeneralWaitBinding; +import com.mithrilmania.blocktopograph.map.Biome; + + +public final class UiUtil { + + public static void toastError(@NonNull Context context) { + Toast.makeText(context, R.string.error_general, Toast.LENGTH_SHORT).show(); + } + + public static void toast(@NonNull Context context, @NonNull String text) { + Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); + } + + public static void toast(@NonNull Context context, @StringRes int resId) { + Toast.makeText(context, resId, Toast.LENGTH_SHORT).show(); + } + + public static void snackError(@NonNull View view) { + Snackbar.make(view, R.string.error_general, Snackbar.LENGTH_SHORT).show(); + } + + public static void snack(@NonNull View view, @NonNull String text) { + Snackbar.make(view, text, Snackbar.LENGTH_SHORT).show(); + } + + public static void snack(@NonNull Activity activity, @NonNull String text) { + snack(activity.getWindow().getDecorView(), text); + } + + public static void snack(@NonNull View view, @StringRes int resId) { + Snackbar.make(view, resId, Snackbar.LENGTH_SHORT).show(); + } + + public static void snack(@NonNull Activity activity, @StringRes int resId) { + snack(activity.getWindow().getDecorView(), resId); + } + + public static void blendBlockColor(@NonNull View view, KnownBlockRepr block) { + Drawable drawable = view.getBackground(); + if (!(drawable instanceof GradientDrawable)) return; + GradientDrawable gradientDrawable = (GradientDrawable) drawable; + int res = (block.id == 0) ? 0 : ColorUtils.blendARGB(block.color, 0x7f7f7f7f, 0.5f); + gradientDrawable.setColor(res); + } + + public static void blendBlockColor(@NonNull View view, ListingBlock block) { + Drawable drawable = view.getBackground(); + if (!(drawable instanceof GradientDrawable)) return; + GradientDrawable gradientDrawable = (GradientDrawable) drawable; + int color = block.getColor(); + if (color != Color.TRANSPARENT) + color = ColorUtils.blendARGB(color, 0x7f7f7f7f, 0.5f); + gradientDrawable.setColor(color); + } + + public static void blendBlockColor(@NonNull View view, BlockTemplate block) { + Drawable drawable = view.getBackground(); + if (!(drawable instanceof GradientDrawable)) return; + GradientDrawable gradientDrawable = (GradientDrawable) drawable; + int color = block.getColor(); + if (color != Color.TRANSPARENT) + color = ColorUtils.blendARGB(color, 0x7f7f7f7f, 0.5f); + gradientDrawable.setColor(color); + } + + public static void blendBlockColor(@NonNull View view, Biome biome) { + Drawable drawable = view.getBackground(); + if (!(drawable instanceof GradientDrawable)) return; + GradientDrawable gradientDrawable = (GradientDrawable) drawable; + int res = ColorUtils.blendARGB(biome.color.asARGB(), 0x7f7f7f7f, 0.5f); + gradientDrawable.setColor(res); + } + + @Nullable + public static Integer readIntFromView(@NonNull EditText editText, boolean emptyAsZero) { + String string = editText.getText().toString(); + if (emptyAsZero && string.isEmpty()) return 0; + try { + return Integer.parseInt(string); + } catch (NumberFormatException e) { + return null; + } + } + + public static int readIntFromView(@NonNull EditText editText) { + String string = editText.getText().toString(); + try { + return Integer.parseInt(string); + } catch (NumberFormatException e) { + return 0; + } + } + + public static int readIntFromViewWithDefault(@NonNull EditText editText, int defaultVal) { + String string = editText.getText().toString(); + if (string.trim().isEmpty()) return defaultVal; + try { + return Integer.parseInt(string); + } catch (NumberFormatException e) { + return 0; + } + } + + + public static AlertDialog buildProgressWaitDialog( + @NonNull Context context, @StringRes int text, + @Nullable DialogInterface.OnCancelListener onCancelListener) { + GeneralWaitBinding binding = DataBindingUtil.inflate( + LayoutInflater.from(context), + R.layout.general_wait, null, false + ); + binding.setText(text); + AlertDialog dialog = new AlertDialog.Builder(context) + .setView(binding.getRoot()) + .setCancelable(onCancelListener != null) + .create(); + if (onCancelListener != null) dialog.setOnCancelListener(onCancelListener); + else dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); + return dialog; + } + + public static float dpToPx(@NonNull Context context, float dp) { + return context.getResources().getDisplayMetrics().density * dp; + } + + public static int dpToPxInt(@NonNull Context context, int dp) { + return (int) (context.getResources().getDisplayMetrics().density * dp); + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/io/IOUtil.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/io/IOUtil.java deleted file mode 100644 index fdad558f..00000000 --- a/app/src/main/java/com/mithrilmania/blocktopograph/util/io/IOUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.mithrilmania.blocktopograph.util.io; - - -import java.io.File; -import java.util.Locale; - -public class IOUtil { - - /** - * Returns the size of a folder (total of contents) in number of bytes. - * Returns 0 if it doesn't exist. - * @param f folder to get size of. - * @return size of folder f in bytes. - */ - public static long getFolderSize(File f) { - long size = 0; - if (f.isDirectory()) { - for (File file : f.listFiles()) { - size += getFolderSize(file); - } - } else { - size = f.length(); - } - return size; - } - - /** - * Simple helper function to get the size of a folder or file in text format, - * @param f file to return size of - * @return size, formatted with a "B", "MB, "GB" or "TB", precise to 2 decimals. - */ - public static String getFileSizeInText(File f){ - long size = getFolderSize(f); - if(size < 1024) return size + " B"; - double v = size / 1024.0; - String suffix = "KB"; - if(v > 1024.0){ - v /= 1024.0; - if(v > 1024.0){ - v /= 1024.0; - if(v > 1024.0){ - v /= 1024.0; - suffix = "TB";//very high end android device here - } - else suffix = "GB"; - } - else suffix = "MB"; - } - - return String.format(Locale.ENGLISH, "%.2f %s", v, suffix); - - } -} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/util/io/TextFile.java b/app/src/main/java/com/mithrilmania/blocktopograph/util/io/TextFile.java deleted file mode 100644 index ec53a145..00000000 --- a/app/src/main/java/com/mithrilmania/blocktopograph/util/io/TextFile.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.mithrilmania.blocktopograph.util.io; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; - -public class TextFile { - - /** Read text file in sync, only use this when appropriate... not in UI **/ - public static String readTextFile(File txtFile){ - StringBuilder text = new StringBuilder(); - BufferedReader br; - try { - br = new BufferedReader(new FileReader(txtFile)); - String line; - while ((line = br.readLine()) != null) { - text.append(line).append('\n'); - } - br.close(); - } - catch (IOException e) { - e.printStackTrace(); - - } - return text.toString(); - } - - public static String readTextFileFirstLine(File txtFile){ - String text = null; - BufferedReader br; - try { - br = new BufferedReader(new FileReader(txtFile)); - text = br.readLine(); - br.close(); - } - catch (IOException e) { - e.printStackTrace(); - } - return text; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/view/MeowExpansionLayout.java b/app/src/main/java/com/mithrilmania/blocktopograph/view/MeowExpansionLayout.java new file mode 100644 index 00000000..2075dd87 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/view/MeowExpansionLayout.java @@ -0,0 +1,174 @@ +package com.mithrilmania.blocktopograph.view; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.util.AttributeSet; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.EdgeEffect; + +import com.github.florent37.expansionpanel.ExpansionLayout; +import com.mithrilmania.blocktopograph.Log; + +import java.lang.reflect.Field; + +import androidx.core.widget.NestedScrollView; + +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +/** + * The class serves two purpose, for layout height fix and edge effect on expansion. + * + *

+ * Unlike a usual use case of the ExpansionLayout as nested scrollable component, + * a "wrap content if space, or match parent if not" behavior was wanted here. + * So a fix/workaround at expansion time and after expansion was needed. + *

+ * Also a glowing edge effect at the top was wanted, in order to indicate + * that the current view was scrollable, and there're content below. + *

+ */ +public class MeowExpansionLayout extends ExpansionLayout { + + /** + * Top edge effect of the underlying NestedScrollView. + */ + private EdgeEffect mEdgeEffect; + + public MeowExpansionLayout(Context context) { + super(context); + init(); + } + + public MeowExpansionLayout(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public MeowExpansionLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + Class clazz = NestedScrollView.class; + try { + Field edgeGlowField = clazz.getDeclaredField("mEdgeGlowTop"); + edgeGlowField.setAccessible(true); + Context context = getContext(); + EdgeEffect edge = new EdgeEffect(context); + edgeGlowField.set(this, edge); + //mEdgeEffect = (EdgeEffect) edgeGlowField.get(this); + edgeGlowField.setAccessible(false); + edgeGlowField = clazz.getDeclaredField("mEdgeGlowBottom"); + edgeGlowField.setAccessible(true); + edgeGlowField.set(this, new EdgeEffect(context)); + edgeGlowField.setAccessible(false); + edge.setSize(20, 20); + mEdgeEffect = edge; + //post(this::doOverScroll); + } catch (Exception e) { + Log.d(this, e); + } + } + + /** + * Extended to fix display bug. + * + *

+ * ScrollViews does not fit well in a limited space without a preset height. + * This was used to apply a "wrap content if space, or match parent if not" rule. + *

+ * + * @param animated Whether display expansion animation. Always true. + */ + @Override + public void expand(boolean animated) { + if (!isEnabled() || isExpanded()) { + return; + } + + if (animated) { + final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, getChildAt(0).getHeight()); + valueAnimator.addUpdateListener(valueAnimator1 -> + setHeightValue((Float) valueAnimator1.getAnimatedValue())); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + setHeight(WRAP_CONTENT); + setAnimator(null); + doOverScroll(); + } + }); + setExpanded(true); + setAnimator(valueAnimator); + valueAnimator.start(); + } else { + // Behavior w/o animation was unchanged. + setHeightValue(getChildAt(0).getHeight()); + setExpanded(true); + } + } + + /** + * Set height with given value if space, or max remaining value if not. + * + *

+ * This must be the last child of a vertical LinearLayout with match_parent height. + *

+ * + * @param height desired height, might not be the final actual height of the view. + */ + private void setHeightValue(float height) { + ViewParent parent = getParent(); + if (parent instanceof ViewGroup) { + float remaining = ((ViewGroup) parent).getMeasuredHeight() - getY(); + height = Math.min(remaining, height); + //Log.d(this, "remaining: " + remaining + ", requested: " + height); + setHeight((int) height); + } + } + + private void setHeight(int height) { + final ViewGroup.LayoutParams layoutParams = getLayoutParams(); + if (layoutParams != null) { + layoutParams.height = height; + setLayoutParams(layoutParams); + } + } + + private void setAnimator(Animator animator) { + try { + Class clazz = ExpansionLayout.class; + Field fieldAnimator = clazz.getDeclaredField("animator"); + fieldAnimator.setAccessible(true); + fieldAnimator.set(this, animator); + fieldAnimator.setAccessible(false); + } catch (Throwable e) { + Log.d(this, e); + } + } + + private void setExpanded(boolean expanded) { + try { + Class clazz = ExpansionLayout.class; + Field fieldAnimator = clazz.getDeclaredField("expanded"); + fieldAnimator.setAccessible(true); + fieldAnimator.setBoolean(this, expanded); + fieldAnimator.setAccessible(false); + } catch (Throwable e) { + Log.d(this, e); + } + } + + public void doOverScroll() { + if (mEdgeEffect != null) { + mEdgeEffect.onPull(200); + invalidate(); + } + } + +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/view/MeowScrollView.java b/app/src/main/java/com/mithrilmania/blocktopograph/view/MeowScrollView.java new file mode 100644 index 00000000..b5c5a823 --- /dev/null +++ b/app/src/main/java/com/mithrilmania/blocktopograph/view/MeowScrollView.java @@ -0,0 +1,64 @@ +package com.mithrilmania.blocktopograph.view; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.EdgeEffect; +import android.widget.ScrollView; + +import com.mithrilmania.blocktopograph.Log; + +import java.lang.reflect.Field; + +public class MeowScrollView extends ScrollView { + + /** + * Top glowing effect of the underlying scrollView. + * + *

It was retrieved via reflection and used later.

+ */ + private EdgeEffect mEdgeEffect; + + public MeowScrollView(Context context) { + super(context); + init(); + } + + public MeowScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public MeowScrollView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public MeowScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init() { + Class clazz = ScrollView.class; + try { + Field edgeGlowField = clazz.getDeclaredField("mEdgeGlowTop"); + edgeGlowField.setAccessible(true); + mEdgeEffect = (EdgeEffect) edgeGlowField.get(this); + edgeGlowField.setAccessible(false); + mEdgeEffect.setSize(20, 20); + post(this::doOverScroll); + } catch (Exception e) { + Log.d(this, e); + } + } + + public void doOverScroll() { + if (mEdgeEffect != null) { + mEdgeEffect.onPull(200); + invalidate(); + } + } +} diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailActivity.java index 93227237..c0c72ee9 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailActivity.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailActivity.java @@ -3,9 +3,9 @@ import android.content.Intent; import android.os.Bundle; -import android.support.v7.widget.Toolbar; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.app.ActionBar; +import androidx.appcompat.widget.Toolbar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.ActionBar; import android.view.MenuItem; import com.mithrilmania.blocktopograph.R; diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailFragment.java b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailFragment.java index 0df821b8..dd7b8b15 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailFragment.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemDetailFragment.java @@ -1,28 +1,36 @@ package com.mithrilmania.blocktopograph.worldlist; +import android.annotation.SuppressLint; import android.app.Activity; -import android.content.Context; import android.content.Intent; -import android.support.design.widget.CollapsingToolbarLayout; +import android.os.AsyncTask; import android.os.Bundle; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.databinding.DataBindingUtil; +import androidx.fragment.app.Fragment; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.snackbar.Snackbar; +import com.mithrilmania.blocktopograph.BackupActivity; +import com.mithrilmania.blocktopograph.Log; import com.mithrilmania.blocktopograph.R; import com.mithrilmania.blocktopograph.World; import com.mithrilmania.blocktopograph.WorldActivity; -import com.mithrilmania.blocktopograph.util.io.IOUtil; +import com.mithrilmania.blocktopograph.backup.WorldBackups; +import com.mithrilmania.blocktopograph.databinding.WorlditemDetailBinding; +import com.mithrilmania.blocktopograph.test.MainTestActivity; +import com.mithrilmania.blocktopograph.util.IoUtil; +import com.mithrilmania.blocktopograph.util.UiUtil; + +import org.apache.commons.io.FileUtils; + +import java.util.Arrays; +import java.util.Date; /** * A fragment representing a single WorldItem detail screen. @@ -30,12 +38,15 @@ * in two-pane mode (on tablets) or a {@link WorldItemDetailActivity} * on handsets. */ -public class WorldItemDetailFragment extends Fragment { +public class WorldItemDetailFragment extends Fragment implements View.OnClickListener { /** * The dummy content this fragment is presenting. */ - private World world; + private static final byte[] SEQ_TEST = {0, 1, 1, 0}; + + private World mWorld; + private byte[] mSequence; /** * Mandatory empty constructor for the fragment manager to instantiate the @@ -44,150 +55,125 @@ public class WorldItemDetailFragment extends Fragment { public WorldItemDetailFragment() { } - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - } - - private String getDate(long time) { - Calendar cal = Calendar.getInstance(); - TimeZone tz = cal.getTimeZone();//get your local time zone. - SimpleDateFormat sdf = new SimpleDateFormat(getString(R.string.full_date_format), Locale.ENGLISH); - sdf.setTimeZone(tz);//set time zone. - return sdf.format(new Date(time * 1000)); - } +// private String getDate(long time) { +// Calendar cal = Calendar.getInstance(); +// TimeZone tz = cal.getTimeZone();//get your local time zone. +// SimpleDateFormat sdf = new SimpleDateFormat(getString(R.string.full_date_format), Locale.ENGLISH); +// sdf.setTimeZone(tz);//set time zone. +// return sdf.format(new Date(time * 1000)); +// } + @SuppressLint("StaticFieldLeak") @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + WorlditemDetailBinding binding = DataBindingUtil.inflate(inflater, R.layout.worlditem_detail, container, false); Activity activity = this.getActivity(); + assert activity != null; String barTitle; - if(!getArguments().containsKey(World.ARG_WORLD_SERIALIZED)){ - Snackbar.make(activity.findViewById(R.id.worlditem_detail), + Bundle arguments = getArguments(); + if (arguments == null || !arguments.containsKey(World.ARG_WORLD_SERIALIZED)) { + Snackbar.make(binding.worlditemDetail, R.string.error_could_not_open_world_details_lost_track_world, Snackbar.LENGTH_LONG) .setAction("Action", null).show(); barTitle = activity.getString(R.string.error_could_not_open_world); } else { - - world = (World) getArguments().getSerializable(World.ARG_WORLD_SERIALIZED); - barTitle = world ==null ? activity.getString(R.string.error_could_not_open_world) : world.getWorldDisplayName(); + mWorld = (World) arguments.getSerializable(World.ARG_WORLD_SERIALIZED); + barTitle = mWorld == null ? activity.getString(R.string.error_could_not_open_world) : mWorld.getWorldDisplayName(); } - CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) activity.findViewById(R.id.toolbar_layout); + CollapsingToolbarLayout appBarLayout = activity.findViewById(R.id.toolbar_layout); if (appBarLayout != null) { appBarLayout.setTitle(barTitle); } - - View rootView = inflater.inflate(R.layout.worlditem_detail, container, false); - try { - if (world != null && world.level != null){ - TextView worldName = (TextView) rootView.findViewById(R.id.detail_world_name); - worldName.setText(world.getWorldDisplayName()); - TextView worldSize = (TextView) rootView.findViewById(R.id.detail_world_size); - worldSize.setText(IOUtil.getFileSizeInText(world.worldFolder)); - - TextView worldGameMode = (TextView) rootView.findViewById(R.id.detail_world_gamemode); - worldGameMode.setText(WorldListUtil.getWorldGamemodeText(activity, world)); - - TextView lastPlayed = (TextView) rootView.findViewById(R.id.detail_last_played); - lastPlayed.setText(WorldListUtil.getLastPlayedText(activity, world)); - - TextView worldSeed = (TextView) rootView.findViewById(R.id.detail_world_seed); - worldSeed.setText(String.valueOf(world.getWorldSeed())); - - TextView worldPath = (TextView) rootView.findViewById(R.id.detail_world_path); - worldPath.setText(world.levelFile.getAbsolutePath()); + if (mWorld != null && mWorld.getLevel() != null) { + binding.setName(mWorld.getWorldDisplayName()); + binding.setSize(IoUtil.getFileSizeInText(FileUtils.sizeOf(mWorld.worldFolder))); + binding.setMode(WorldListUtil.getWorldGamemodeText(activity, mWorld)); + binding.setTime(WorldListUtil.getLastPlayedText(activity, mWorld)); + binding.setSeed(String.valueOf(mWorld.getWorldSeed())); + binding.setPath(mWorld.levelFile.getAbsolutePath()); } - } catch (Exception e){ - e.printStackTrace(); + } catch (Exception e) { + Log.d(this, e); } + binding.fabOpenWorld.setOnClickListener(view -> { + WorldBackups worldBackups = new WorldBackups(mWorld); + worldBackups.loadConfig(); + if (worldBackups.autoBackup) { + AlertDialog dia = UiUtil.buildProgressWaitDialog(view.getContext(), + R.string.auto_backup_caption, null); + dia.show(); + new AsyncTask() { + @Override + protected Boolean doInBackground(WorldBackups... worldBackups) { + return worldBackups[0].createNewBackup(getString(R.string.auto_backup_name), new Date()); + } - FloatingActionButton fabOpenWorld = (FloatingActionButton) rootView.findViewById(R.id.fab_open_world); - assert fabOpenWorld != null; - fabOpenWorld.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, R.string.loading_world, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - - Context context = view.getContext(); - Intent intent = new Intent(context, WorldActivity.class); - intent.putExtra(World.ARG_WORLD_SERIALIZED, world); - - context.startActivity(intent); - } - }); - - // Debug button to write small worlds in an easily readable format - // WARNING: DO NOT USE ON LARGE WORLDS (The debug output will get way larger than the world!) - /* - FloatingActionButton fabDevMode = (FloatingActionButton) rootView.findViewById(R.id.fab_dev_mode); - assert fabDevMode != null; - fabDevMode.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, "Outputting world...", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - - WorldData wData = world.getWorldData(); - - - - File outputFile = new File(world.worldFolder, "debug_hex_out.txt"); - - try { - - wData.load(); - wData.openDB(); - Iterator it = wData.db.iterator(); - - BufferedWriter buf = new BufferedWriter(new FileWriter(outputFile, false), 1024); - - for(it.seekToFirst(); it.isValid(); it.next()){ - byte[] key = it.getKey(); - byte[] value = it.getValue(); - - buf.newLine(); - buf.newLine(); - buf.write("========================"); - buf.newLine(); - buf.write("key: " + new String(key)); - buf.newLine(); - buf.write("key in Hex: " + WorldData.bytesToHex(key, 0, key.length)); - buf.newLine(); - buf.write("------------------------"); - buf.newLine(); - for(int i =0; i < value.length; i += 256){ - buf.write(WorldData.bytesToHex(value, i, Math.min(i + 256, value.length))); - buf.newLine(); + @Override + protected void onPostExecute(Boolean aBoolean) { + if (!aBoolean) { + Activity activity1 = getActivity(); + if (activity1 != null) + UiUtil.snack(activity1, R.string.general_failed); } - + synchronized (dia) { + if (dia.isShowing()) dia.dismiss(); + } + startWorldActivity(); } + }.execute(worldBackups); + } else startWorldActivity(); + }); - buf.close(); + mSequence = new byte[]{-1, -1, -1, -1}; + binding.buttonLeft.setOnClickListener(this); + binding.buttonRight.setOnClickListener(this); + binding.buttonBackup.setOnClickListener(this); - it.close(); - wData.closeDB(); + return binding.getRoot(); + } - } - catch (Exception e) { - Log.e("Failed writing debug file to "+outputFile.getAbsolutePath()+"\n" + e.toString()); - } + private void startWorldActivity() { - Snackbar.make(view, "Done outputting world!!! Path: "+outputFile.getAbsolutePath(), Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); + Activity activity = getActivity(); + assert activity != null; + activity.startActivity( + new Intent(activity, WorldActivity.class) + .putExtra(World.ARG_WORLD_SERIALIZED, mWorld)); + } - } - });*/ + private void sequence(byte code) { + int pos = mSequence.length - 1; + System.arraycopy(mSequence, 1, mSequence, 0, pos); + mSequence[pos] = code; + if (Arrays.equals(mSequence, SEQ_TEST)) { + startActivity( + new Intent(getActivity(), MainTestActivity.class) + .putExtra(World.ARG_WORLD_SERIALIZED, mWorld) + ); + } + } - return rootView; + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.button_left: + sequence((byte) 0); + break; + case R.id.button_right: + sequence((byte) 1); + break; + case R.id.button_backup: + startActivity(new Intent(getActivity(), BackupActivity.class).putExtra(World.ARG_WORLD_SERIALIZED, mWorld)); + break; + } } } diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemListActivity.java b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemListActivity.java index 088e17f8..a5d3e0ec 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemListActivity.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldItemListActivity.java @@ -3,23 +3,15 @@ import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; -import android.support.annotation.NonNull; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.NavigationView; -import android.support.design.widget.Snackbar; -import android.support.v4.app.ActivityCompat; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.Toolbar; import android.text.Editable; -import android.text.Html; +import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.Menu; @@ -29,41 +21,118 @@ import android.widget.EditText; import android.widget.TextView; -import com.mithrilmania.blocktopograph.BuildConfig; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ActivityCompat; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; +import com.mithrilmania.blocktopograph.CreateWorldActivity; import com.mithrilmania.blocktopograph.Log; -import com.mithrilmania.blocktopograph.MenuHelper; import com.mithrilmania.blocktopograph.R; import com.mithrilmania.blocktopograph.World; -import com.mithrilmania.blocktopograph.WorldActivity; -import com.mithrilmania.blocktopograph.util.io.IOUtil; +import com.mithrilmania.blocktopograph.backup.WorldBackups; +import com.mithrilmania.blocktopograph.util.IoUtil; + +import org.apache.commons.io.FileUtils; import java.io.File; -import java.io.FileFilter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -public class WorldItemListActivity extends AppCompatActivity implements MenuHelper.MenuContext { +public class WorldItemListActivity extends AppCompatActivity { + // Storage Permissions + private static final int REQUEST_EXTERNAL_STORAGE = 4242; + private static final String[] PERMISSIONS_STORAGE = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + }; + public static final int REQUEST_CODE_CREATE_WORLD = 2012; + public static final String PREF_KEY_ACCEPT_DATA_USAGE = "accept_data_usage"; /** - * Whether or not the activity is in two-pane mode, i.e. running on a tablet - * device. + * Whether or not the activity is in two-pane mode, d.e. running on a tablet. */ private boolean mTwoPane; - private WorldItemRecyclerViewAdapter worldItemAdapter; + /** + * Checks if the app has permission to write to device storage + *

+ * If the app does not has permission then the user will be prompted to grant permissions + *

+ */ + public static boolean verifyStoragePermissions(Activity activity) { + // Check if we have write permission + boolean hasPermission = true; + for (String permission : PERMISSIONS_STORAGE) { + int state = ActivityCompat.checkSelfPermission(activity, permission); + if (state != PackageManager.PERMISSION_GRANTED) { + hasPermission = false; + break; + } + } + + if (!hasPermission) { + // We don't have permission so prompt the user + ActivityCompat.requestPermissions( + activity, + PERMISSIONS_STORAGE, + REQUEST_EXTERNAL_STORAGE + ); + return false; + } else return true; + } + + private void showFeedbackRequestDialogIfNeeded() { + SharedPreferences prefs = getPreferences(MODE_PRIVATE); + if (prefs.getInt(PREF_KEY_ACCEPT_DATA_USAGE, 0) == 1) { + Log.enableCrashlytics(); + Log.enableFirebaseAnalytics(this); + return; + } + AlertDialog dialog = new AlertDialog.Builder(this) + .setTitle(R.string.privacy_promo_title) + .setMessage(R.string.privacy_promo_text) + .setPositiveButton(R.string.privacy_promo_accept_btn, this::onAcceptedRequestDialog) + .setNegativeButton(R.string.privacy_promo_reject_btn, this::onRejectedRequestDialog) + .setCancelable(false) + .create(); + dialog.setCanceledOnTouchOutside(false); + dialog.show(); + View view = dialog.findViewById(android.R.id.message); + if (view instanceof TextView) + ((TextView) view).setMovementMethod(LinkMovementMethod.getInstance()); + else Log.d(this, "cannot find android.R.id.message for privacy request dialog."); + } + + private void onAcceptedRequestDialog(DialogInterface dialogInterface, int i) { + Log.enableFirebaseAnalytics(this); + Log.enableCrashlytics(); + getPreferences(MODE_PRIVATE).edit().putInt(PREF_KEY_ACCEPT_DATA_USAGE, 1).apply(); + } + + private void onRejectedRequestDialog(DialogInterface dialogInterface, int i) { + finishAffinity(); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.activity_worldlist); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); - assert toolbar != null; toolbar.setTitle(getTitle()); setSupportActionBar(toolbar); + showFeedbackRequestDialogIfNeeded(); if (findViewById(R.id.worlditem_detail_container) != null) { // The detail container view will be present only in the @@ -73,37 +142,118 @@ protected void onCreate(Bundle savedInstanceState) { mTwoPane = true; } - - FloatingActionButton fabRefreshWorlds = (FloatingActionButton) findViewById(R.id.fab_refresh_worlds); - assert fabRefreshWorlds != null; - fabRefreshWorlds.setOnClickListener(new View.OnClickListener() { + FloatingActionButton fabChooseWorldFile = findViewById(R.id.fab_create); + fabChooseWorldFile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { + onClickCreateWorld(); + } + }); - if(worldItemAdapter != null){ - if(worldItemAdapter.reloadWorldList()) { - Snackbar.make(view, R.string.reloaded_world_list, Snackbar.LENGTH_SHORT) - .setAction("Action", null).show(); - } else { - Snackbar.make(view, R.string.could_not_find_worlds, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - } else { - Snackbar.make(view, R.string.no_read_write_access, Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } + RecyclerView recyclerView = findViewById(R.id.worlditem_list); + worldItemAdapter = new WorldItemRecyclerViewAdapter(); + recyclerView.setAdapter(this.worldItemAdapter); + + if (verifyStoragePermissions(this)) { + //directly open the world list if we already have access + worldItemAdapter.enable(); + } + + + } + private void onClickCreateWorld() { + if (worldItemAdapter.isDisabled()) { + Snackbar.make(getWindow().getDecorView(), R.string.no_read_write_access, Snackbar.LENGTH_SHORT).show(); + return; + } + startActivityForResult(new Intent(this, CreateWorldActivity.class), REQUEST_CODE_CREATE_WORLD); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (resultCode == RESULT_OK) { + switch (requestCode) { + case REQUEST_CODE_CREATE_WORLD: + worldItemAdapter.loadWorldList(); + return; } - }); + } + super.onActivityResult(requestCode, resultCode, data); + } + private boolean checkPermissions(@NonNull int[] grantResults) { + for (int result : grantResults) + if (result != PackageManager.PERMISSION_GRANTED) return false; + return true; + } - FloatingActionButton fabChooseWorldFile = (FloatingActionButton) findViewById(R.id.fab_choose_worldfile); - assert fabChooseWorldFile != null; - fabChooseWorldFile.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(final View view) { + @Override + public void onRequestPermissionsResult(int requestCode, + @NonNull String[] permissions, @NonNull int[] grantResults) { + switch (requestCode) { + case REQUEST_EXTERNAL_STORAGE: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length == PERMISSIONS_STORAGE.length && checkPermissions(grantResults)) { + + // permission was granted, yay! + this.worldItemAdapter.enable(); + } else { + // permission denied, boo! Disable the + AlertDialog.Builder builder = new AlertDialog.Builder(this); + TextView msg = new TextView(this); + float dpi = this.getResources().getDisplayMetrics().density; + msg.setPadding((int) (19 * dpi), (int) (5 * dpi), (int) (14 * dpi), (int) (5 * dpi)); + msg.setMaxLines(20); + msg.setMovementMethod(LinkMovementMethod.getInstance()); + msg.setText(R.string.no_sdcard_access); + builder.setView(msg) + .setTitle(R.string.action_help) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, null) + .show(); + } + } + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.world, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + Bundle params = new Bundle(); + int type; + switch (item.getItemId()) { + case R.id.action_open: + type = Log.ANA_PARAM_MAINACT_MENU_TYPE_OPEN; + break; + case R.id.action_help: + type = Log.ANA_PARAM_MAINACT_MENU_TYPE_HELP; + break; + case R.id.action_about: + type = Log.ANA_PARAM_MAINACT_MENU_TYPE_ABOUT; + break; + default: + type = 0; + } + params.putInt(Log.ANA_PARAM_MAINACT_MENU_TYPE, type); + Log.logFirebaseEvent(this, Log.CustomFirebaseEvent.MAINACT_MENU_OPEN, params); + + //some text pop-up dialogs, some with simple HTML tags. + switch (item.getItemId()) { + case R.id.action_open: { + if (worldItemAdapter.isDisabled()) { + Snackbar.make(getWindow().getDecorView(), R.string.no_read_write_access, Snackbar.LENGTH_SHORT).show(); + return true; + } final EditText pathText = new EditText(WorldItemListActivity.this); pathText.setHint(R.string.storage_path_here); @@ -117,29 +267,29 @@ public void onClick(DialogInterface dialog, int whichButton) { //new tag name Editable pathEditable = pathText.getText(); String path = (pathEditable == null || pathEditable.toString().equals("")) ? null : pathEditable.toString(); - if(path == null){ + if (path == null) { return;//no path, no world } String levelDat = "/level.dat"; int levelIndex = path.lastIndexOf(levelDat); //if the path ends with /level.dat, remove it! - if(levelIndex >= 0 && path.endsWith(levelDat)) + if (levelIndex >= 0 && path.endsWith(levelDat)) path = path.substring(0, levelIndex); - String defaultPath = Environment.getExternalStorageDirectory().toString()+"/games/com.mojang/minecraftWorlds/"; + String defaultPath = Environment.getExternalStorageDirectory().toString() + "/games/com.mojang/minecraftWorlds/"; File worldFolder = new File(path); String errTitle = null, errMsg = String.format(getString(R.string.report_path_and_previous_search), path, defaultPath); - if(!worldFolder.exists()){ + if (!worldFolder.exists()) { errTitle = getString(R.string.no_file_folder_found_at_path); } - if(!worldFolder.isDirectory()){ + if (!worldFolder.isDirectory()) { errTitle = getString(R.string.worldpath_is_not_directory); } - if(!(new File(worldFolder, "level.dat").exists())){ + if (!(new File(worldFolder, "level.dat").exists())) { errTitle = getString(R.string.no_level_dat_found); } - if(errTitle != null) { + if (errTitle != null) { new AlertDialog.Builder(WorldItemListActivity.this) .setTitle(errTitle) .setMessage(errMsg) @@ -149,7 +299,7 @@ public void onClick(DialogInterface dialog, int whichButton) { } else { try { - World world = new World(worldFolder); + World world = new World(worldFolder, null, WorldItemListActivity.this); if (mTwoPane) { Bundle arguments = new Bundle(); @@ -166,8 +316,8 @@ public void onClick(DialogInterface dialog, int whichButton) { WorldItemListActivity.this.startActivity(intent); } - } catch (Exception e){ - Snackbar.make(view, R.string.error_opening_world, Snackbar.LENGTH_SHORT) + } catch (Exception e) { + Snackbar.make(getWindow().getDecorView(), R.string.error_opening_world, Snackbar.LENGTH_SHORT) .setAction("Action", null).show(); } } @@ -183,175 +333,145 @@ public void onClick(DialogInterface dialog, int whichButton) { alert.show(); //TODO: browse for custom located world file, not everybody understands filesystem paths + //Then it also cannot find a world. --rbq2012. + return true; } - }); - - - - if(verifyStoragePermissions(this)){ - //directly open the world list if we already have access - initWorldList(); - } - - - } - - public void initWorldList(){ - - View recyclerView = findViewById(R.id.worlditem_list); - assert recyclerView != null; - boolean hasWorlds = setupRecyclerView((RecyclerView) recyclerView); - if(!hasWorlds){ - Snackbar.make(recyclerView, R.string.could_not_find_worlds, Snackbar.LENGTH_SHORT) - .setAction("Action", null).show(); - } - - } - - - @Override - public void onRequestPermissionsResult(int requestCode, - @NonNull String permissions[], @NonNull int[] grantResults) { - switch (requestCode) { - case REQUEST_EXTERNAL_STORAGE: { - // If request is cancelled, the result arrays are empty. - if (grantResults.length > 0 - && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - - // permission was granted, yay! - initWorldList(); - - } else { - - // permission denied, boo! Disable the - AlertDialog.Builder builder = new AlertDialog.Builder(this); - TextView msg = new TextView(this); - float dpi = this.getResources().getDisplayMetrics().density; - msg.setPadding((int)(19*dpi), (int)(5*dpi), (int)(14*dpi), (int)(5*dpi)); - msg.setMaxLines(20); - msg.setMovementMethod(LinkMovementMethod.getInstance()); - msg.setText(R.string.no_sdcard_access); - builder.setView(msg) - .setTitle(R.string.action_help) - .setCancelable(true) - .setNeutralButton(android.R.string.ok, null) - .show(); - } + case R.id.action_about: { + + android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this); + TextView msg = new TextView(this); + msg.setEllipsize(TextUtils.TruncateAt.MARQUEE); + float dpi = getResources().getDisplayMetrics().density; + msg.setPadding((int) (19 * dpi), (int) (5 * dpi), (int) (14 * dpi), (int) (5 * dpi)); + msg.setMaxLines(20); + msg.setMovementMethod(LinkMovementMethod.getInstance()); + msg.setText(R.string.app_about); + builder.setView(msg) + .setTitle(R.string.action_about) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, null) + .show(); + + return true; + } + case R.id.action_help: { + android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this); + TextView msg = new TextView(this); + float dpi = getResources().getDisplayMetrics().density; + msg.setPadding((int) (19 * dpi), (int) (5 * dpi), (int) (14 * dpi), (int) (5 * dpi)); + msg.setMaxLines(20); + msg.setMovementMethod(LinkMovementMethod.getInstance()); + msg.setText(R.string.app_help); + builder.setView(msg) + .setTitle(R.string.action_help) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, null) + .show(); + + return true; + } +// case R.id.action_changelog: { +// AlertDialog.Builder builder = new AlertDialog.Builder(ctx); +// TextView msg = new TextView(ctx); +// float dpi = ctx.getResources().getDisplayMetrics().density; +// msg.setPadding((int) (19 * dpi), (int) (5 * dpi), (int) (14 * dpi), (int) (5 * dpi)); +// msg.setMaxLines(20); +// msg.setMovementMethod(LinkMovementMethod.getInstance()); +// String content = String.format(ctx.getResources().getString(R.string.app_changelog), BuildConfig.VERSION_NAME); +// //noinspection deprecation +// msg.setText(Html.fromHtml(content)); +// builder.setView(msg) +// .setTitle(R.string.action_changelog) +// .setCancelable(true) +// .setNeutralButton(android.R.string.ok, null) +// .show(); +// +// return true; +// } + default: { + return false; } } } - - - // Storage Permissions - private static final int REQUEST_EXTERNAL_STORAGE = 4242; - private static String[] PERMISSIONS_STORAGE = { - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE - }; - - /** - * Checks if the app has permission to write to device storage - * - * If the app does not has permission then the user will be prompted to grant permissions - * - */ - public static boolean verifyStoragePermissions(Activity activity) { - // Check if we have write permission - int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); - - if (permission != PackageManager.PERMISSION_GRANTED) { - // We don't have permission so prompt the user - ActivityCompat.requestPermissions( - activity, - PERMISSIONS_STORAGE, - REQUEST_EXTERNAL_STORAGE - ); - return false; - } else return true; - } - - - //returns true if the list of worlds is not empty - private boolean setupRecyclerView(@NonNull RecyclerView recyclerView) { - this.worldItemAdapter = new WorldItemRecyclerViewAdapter(); - boolean hasWorlds = this.worldItemAdapter.reloadWorldList(); - recyclerView.setAdapter(this.worldItemAdapter); - return hasWorlds; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.world, menu); - return true; - } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return MenuHelper.onOptionsItemSelected(this, item); - } - - @Override - public Context getContext() { - return this; - } - - @Override - public boolean propagateOnOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); + protected void onResume() { + super.onResume(); + worldItemAdapter.loadWorldList(); } public class WorldItemRecyclerViewAdapter extends RecyclerView.Adapter { - private final List mValues; + private final List mWorlds; - private final File savesFolder; + private boolean disabled; WorldItemRecyclerViewAdapter() { - mValues = new ArrayList<>(); + mWorlds = new ArrayList<>(16); + disabled = true; + } - String path = Environment.getExternalStorageDirectory().toString()+"/games/com.mojang/minecraftWorlds/"; - Log.d("minecraftWorlds path: " + path); + void enable() { + disabled = false; + } - this.savesFolder = new File(path); + public boolean isDisabled() { + return disabled; } //returns true if it has loaded a new list of worlds, false otherwise - boolean reloadWorldList(){ - mValues.clear(); - File[] saves = savesFolder.exists() ? savesFolder.listFiles(new FileFilter() { - @Override - public boolean accept(File pathname) { - return new File(pathname + "/level.dat").exists(); - } - }) : null; - - if(saves != null) { - Log.d("Number of minecraft worlds: " + saves.length); - - for (File save : saves) { - //debug if we see all worlds - Log.d("FileName: " + save.getName()); + void loadWorldList() { + if (disabled) return; + mWorlds.clear(); + List saveFolders; + List marks; + saveFolders = new ArrayList<>(4); + marks = new ArrayList<>(4); + + File sd = Environment.getExternalStorageDirectory(); + + saveFolders.add(new File(sd, "games/com.mojang/minecraftWorlds")); + marks.add(null); + + //noinspection ResultOfMethodCallIgnored + new File(sd, "Android/data").listFiles( + file -> { + if (file.getName().startsWith("com.netease")) { + File worldsFolder = new File(file, "files/minecraftWorlds"); + if (worldsFolder.exists()) { + saveFolders.add(worldsFolder); + marks.add(getString(R.string.world_mark_neteas)); + } + } + return false; + } + ); + for (int i = 0, saveFoldersSize = saveFolders.size(); i < saveFoldersSize; i++) { + File dir = saveFolders.get(i); + File[] files = dir.listFiles(file -> { + if (!file.isDirectory()) return false; + return (new File(file, "level.dat").exists() + || new File(file, WorldBackups.BTG_BACKUPS).exists()); + }); + if (files != null) for (File f : files) { try { - mValues.add(new World(save)); + mWorlds.add(new World(f, marks.get(i), WorldItemListActivity.this)); } catch (World.WorldLoadException e) { - e.printStackTrace(); - Log.d("Skipping world while reloading world list: " - + save.getName() + ", loading failed somehow, check stack trace"); + Log.d(this, e); } } } - Collections.sort(mValues, new Comparator() { + Collections.sort(mWorlds, new Comparator() { @Override public int compare(World a, World b) { try { long tA = WorldListUtil.getLastPlayedTimestamp(a); long tB = WorldListUtil.getLastPlayedTimestamp(b); - return tA > tB ? -1 : (tA == tB ? 0 : 1); + return Long.compare(tB, tA); } catch (Exception e) { + Log.d(this, e); return 0; } } @@ -360,72 +480,82 @@ public int compare(World a, World b) { //load data into view this.notifyDataSetChanged(); - return mValues.size() > 0; + if (mWorlds.size() == 0) { + AlertDialog dia = new AlertDialog.Builder(WorldItemListActivity.this) + .setTitle(R.string.err_noworld_1) + .setView(R.layout.dialog_noworlds) + .setPositiveButton(android.R.string.ok, null) + .create(); + dia.show(); + } } - + @NonNull @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.worlditem_list_content, parent, false); return new ViewHolder(view); } - @SuppressLint("SetTextI18n") @Override - public void onBindViewHolder(final ViewHolder holder, int position) { - holder.mWorld = mValues.get(position); + public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { + holder.mWorld = mWorlds.get(position); holder.mWorldNameView.setText(holder.mWorld.getWorldDisplayName()); - holder.mWorldSize.setText(IOUtil.getFileSizeInText(holder.mWorld.worldFolder)); + holder.mWorldSize.setText(IoUtil.getFileSizeInText(FileUtils.sizeOf(holder.mWorld.worldFolder))); holder.mWorldGamemode.setText(WorldListUtil.getWorldGamemodeText(WorldItemListActivity.this, holder.mWorld)); holder.mWorldLastPlayed.setText(WorldListUtil.getLastPlayedText(WorldItemListActivity.this, holder.mWorld)); - holder.mWorldPath.setText(holder.mWorld.levelFile.getAbsolutePath()); - + holder.mWorldPath.setText(holder.mWorld.worldFolder.getName()); + holder.mWorldMark.setText(holder.mWorld.mark); + + + holder.mView.setOnClickListener(v -> { + if (mTwoPane) { + Bundle arguments = new Bundle(); + arguments.putSerializable(World.ARG_WORLD_SERIALIZED, holder.mWorld); + WorldItemDetailFragment fragment = new WorldItemDetailFragment(); + fragment.setArguments(arguments); + getSupportFragmentManager().beginTransaction() + .replace(R.id.worlditem_detail_container, fragment) + .commit(); + } else { + Context context = v.getContext(); + Intent intent = new Intent(context, WorldItemDetailActivity.class); + intent.putExtra(World.ARG_WORLD_SERIALIZED, holder.mWorld); - holder.mView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mTwoPane) { - Bundle arguments = new Bundle(); - arguments.putSerializable(World.ARG_WORLD_SERIALIZED, holder.mWorld); - WorldItemDetailFragment fragment = new WorldItemDetailFragment(); - fragment.setArguments(arguments); - getSupportFragmentManager().beginTransaction() - .replace(R.id.worlditem_detail_container, fragment) - .commit(); - } else { - Context context = v.getContext(); - Intent intent = new Intent(context, WorldItemDetailActivity.class); - intent.putExtra(World.ARG_WORLD_SERIALIZED, holder.mWorld); - - context.startActivity(intent); - } + context.startActivity(intent); } }); } @Override public int getItemCount() { - return mValues.size(); + return mWorlds.size(); } class ViewHolder extends RecyclerView.ViewHolder { final View mView; - final TextView mWorldNameView, mWorldSize, mWorldGamemode, mWorldLastPlayed, mWorldPath; + final TextView mWorldNameView; + final TextView mWorldMark; + final TextView mWorldSize; + final TextView mWorldGamemode; + final TextView mWorldLastPlayed; + final TextView mWorldPath; World mWorld; ViewHolder(View view) { super(view); mView = view; - mWorldNameView = (TextView) view.findViewById(R.id.world_name); - mWorldSize = (TextView) view.findViewById(R.id.world_size); - mWorldGamemode = (TextView) view.findViewById(R.id.world_gamemode); - mWorldLastPlayed = (TextView) view.findViewById(R.id.world_last_played); - mWorldPath = (TextView) view.findViewById(R.id.world_path); + mWorldNameView = view.findViewById(R.id.world_name); + mWorldMark = view.findViewById(R.id.world_mark); + mWorldSize = view.findViewById(R.id.world_size); + mWorldGamemode = view.findViewById(R.id.world_gamemode); + mWorldLastPlayed = view.findViewById(R.id.world_last_played); + mWorldPath = view.findViewById(R.id.world_path); } @Override diff --git a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldListUtil.java b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldListUtil.java index 523f88dc..db2efc5b 100644 --- a/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldListUtil.java +++ b/app/src/main/java/com/mithrilmania/blocktopograph/worldlist/WorldListUtil.java @@ -3,6 +3,7 @@ import android.content.Context; +import com.mithrilmania.blocktopograph.Log; import com.mithrilmania.blocktopograph.R; import com.mithrilmania.blocktopograph.World; @@ -10,41 +11,46 @@ public class WorldListUtil { - public static long getLastPlayedTimestamp(World world){ + public static long getLastPlayedTimestamp(World world) { try { - return (long) world.level.getChildTagByKey("LastPlayed").getValue(); - } catch (Exception e){ + return (long) world.getLevel().getChildTagByKey("LastPlayed").getValue(); + } catch (Exception e) { + Log.d(WorldListUtil.class, e); return 0; } } - public static String getLastPlayedText(Context context, World world){ + public static String getLastPlayedText(Context context, World world) { long lastPlayed = getLastPlayedTimestamp(world); - if(lastPlayed == 0) return "?"; + if (lastPlayed == 0) return "?"; DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context); return dateFormat.format(lastPlayed * 1000); } - public static String getWorldGamemodeText(Context context, World world){ + public static String getWorldGamemodeText(Context context, World world) { String gameMode; try { - int gameType = (int) world.level.getChildTagByKey("GameType").getValue(); - switch (gameType){ - case 0: gameMode = context.getString(R.string.gamemode_survival); + int gameType = (int) world.getLevel().getChildTagByKey("GameType").getValue(); + switch (gameType) { + case 0: + gameMode = context.getString(R.string.gamemode_survival); break; - case 1: gameMode = context.getString(R.string.gamemode_creative); + case 1: + gameMode = context.getString(R.string.gamemode_creative); break; - case 2: gameMode = context.getString(R.string.gamemode_adventure); + case 2: + gameMode = context.getString(R.string.gamemode_adventure); break; default: gameMode = "?"; } - } catch (Exception e){ - gameMode = "?"; + } catch (Exception e) { + Log.d(WorldListUtil.class, e); + gameMode = "??"; } return gameMode; } - - + + } diff --git a/app/src/main/res/drawable-anydpi-v26/ic_launcher.xml b/app/src/main/res/drawable-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..bbd3e021 --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/drawable-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..bbd3e021 --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_action_arrow_right.png b/app/src/main/res/drawable-hdpi/ic_action_arrow_right.png deleted file mode 100644 index 2a284516..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_arrow_right.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_compass.png b/app/src/main/res/drawable-hdpi/ic_action_compass.png deleted file mode 100644 index 80f0034d..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_compass.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_exit.png b/app/src/main/res/drawable-hdpi/ic_action_exit.png deleted file mode 100644 index 708c14ca..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_exit.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_filter.png b/app/src/main/res/drawable-hdpi/ic_action_filter.png deleted file mode 100644 index f741f0f2..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_filter.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_home.png b/app/src/main/res/drawable-hdpi/ic_action_home.png deleted file mode 100644 index 2d78b078..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_home.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_home_b.png b/app/src/main/res/drawable-hdpi/ic_action_home_b.png deleted file mode 100644 index ba1e885b..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_home_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_list.png b/app/src/main/res/drawable-hdpi/ic_action_list.png deleted file mode 100644 index b5f08e02..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_list.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_map.png b/app/src/main/res/drawable-hdpi/ic_action_map.png deleted file mode 100644 index 39348d9b..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_map.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_map_b.png b/app/src/main/res/drawable-hdpi/ic_action_map_b.png deleted file mode 100644 index f5f3b629..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_map_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_puzzle.png b/app/src/main/res/drawable-hdpi/ic_action_puzzle.png deleted file mode 100644 index 3ed2e5a7..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_puzzle.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_save.png b/app/src/main/res/drawable-hdpi/ic_action_save.png deleted file mode 100644 index fe33819e..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_save.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_save_b.png b/app/src/main/res/drawable-hdpi/ic_action_save_b.png deleted file mode 100644 index c06324e2..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_save_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_search.png b/app/src/main/res/drawable-hdpi/ic_action_search.png deleted file mode 100644 index cf650604..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_search.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_settings.png b/app/src/main/res/drawable-hdpi/ic_action_settings.png deleted file mode 100644 index b155a92c..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_action_settings.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_add_location.png b/app/src/main/res/drawable-hdpi/ic_add_location.png deleted file mode 100644 index 9465d585..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_add_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_broken_image.png b/app/src/main/res/drawable-hdpi/ic_broken_image.png deleted file mode 100644 index 5442156e..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_broken_image.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_bubble_chart.png b/app/src/main/res/drawable-hdpi/ic_bubble_chart.png deleted file mode 100644 index e4f0c0e9..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_bubble_chart.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_developer_mode.png b/app/src/main/res/drawable-hdpi/ic_developer_mode.png deleted file mode 100644 index 6b1df6f3..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_developer_mode.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_emoticon.png b/app/src/main/res/drawable-hdpi/ic_emoticon.png deleted file mode 100644 index eb10be9b..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_emoticon.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_emoticon_b.png b/app/src/main/res/drawable-hdpi/ic_emoticon_b.png deleted file mode 100644 index 82cf2090..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_emoticon_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_folder.png b/app/src/main/res/drawable-hdpi/ic_folder.png deleted file mode 100644 index 018f1a3e..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_folder.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_folder_open.png b/app/src/main/res/drawable-hdpi/ic_folder_open.png deleted file mode 100644 index 80dadb5a..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_folder_open.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_gps_fixed.png b/app/src/main/res/drawable-hdpi/ic_gps_fixed.png deleted file mode 100644 index 70f10358..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_gps_fixed.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_gradient.png b/app/src/main/res/drawable-hdpi/ic_gradient.png deleted file mode 100644 index 59cd3327..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_gradient.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_grid_on.png b/app/src/main/res/drawable-hdpi/ic_grid_on.png deleted file mode 100644 index bb112cc4..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_grid_on.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_inventory.png b/app/src/main/res/drawable-hdpi/ic_inventory.png deleted file mode 100644 index 6707c1c4..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_inventory.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_layers.png b/app/src/main/res/drawable-hdpi/ic_layers.png deleted file mode 100644 index d44f2e79..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_layers.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_location.png b/app/src/main/res/drawable-hdpi/ic_location.png deleted file mode 100644 index 20398c5a..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_nature_people.png b/app/src/main/res/drawable-hdpi/ic_nature_people.png deleted file mode 100644 index 377c66f8..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_nature_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_people.png b/app/src/main/res/drawable-hdpi/ic_people.png deleted file mode 100644 index 2eef401f..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_people_outline.png b/app/src/main/res/drawable-hdpi/ic_people_outline.png deleted file mode 100644 index f52c4c24..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_people_outline.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_person.png b/app/src/main/res/drawable-hdpi/ic_person.png deleted file mode 100644 index faad1f66..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_person.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_person_pin_circle.png b/app/src/main/res/drawable-hdpi/ic_person_pin_circle.png deleted file mode 100644 index d5ea7161..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_person_pin_circle.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_place.png b/app/src/main/res/drawable-hdpi/ic_place.png deleted file mode 100644 index c214dc24..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_place.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_player.png b/app/src/main/res/drawable-hdpi/ic_player.png deleted file mode 100644 index 65974a22..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_player.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_priority_high.png b/app/src/main/res/drawable-hdpi/ic_priority_high.png deleted file mode 100644 index 54ddd735..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_priority_high.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_refresh.png b/app/src/main/res/drawable-hdpi/ic_refresh.png deleted file mode 100644 index ac7f012e..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_refresh.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_satellite.png b/app/src/main/res/drawable-hdpi/ic_satellite.png deleted file mode 100644 index 37c0c546..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_satellite.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_settings_brightness.png b/app/src/main/res/drawable-hdpi/ic_settings_brightness.png deleted file mode 100644 index 19058a99..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_settings_brightness.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_terrain.png b/app/src/main/res/drawable-hdpi/ic_terrain.png deleted file mode 100644 index 3b8492c8..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_terrain.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_visibility.png b/app/src/main/res/drawable-hdpi/ic_visibility.png deleted file mode 100644 index 8d7ba24b..00000000 Binary files a/app/src/main/res/drawable-hdpi/ic_visibility.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_arrow_right.png b/app/src/main/res/drawable-mdpi/ic_action_arrow_right.png deleted file mode 100644 index e52be1e4..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_arrow_right.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_compass.png b/app/src/main/res/drawable-mdpi/ic_action_compass.png deleted file mode 100644 index e8bce9dd..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_compass.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_exit.png b/app/src/main/res/drawable-mdpi/ic_action_exit.png deleted file mode 100644 index b58f15aa..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_exit.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_filter.png b/app/src/main/res/drawable-mdpi/ic_action_filter.png deleted file mode 100644 index e2a95775..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_filter.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_home.png b/app/src/main/res/drawable-mdpi/ic_action_home.png deleted file mode 100644 index 723db82c..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_home.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_home_b.png b/app/src/main/res/drawable-mdpi/ic_action_home_b.png deleted file mode 100644 index 12915c6c..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_home_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_list.png b/app/src/main/res/drawable-mdpi/ic_action_list.png deleted file mode 100644 index 13305ef3..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_list.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_map.png b/app/src/main/res/drawable-mdpi/ic_action_map.png deleted file mode 100644 index a2aa7501..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_map.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_map_b.png b/app/src/main/res/drawable-mdpi/ic_action_map_b.png deleted file mode 100644 index 3adc16ee..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_map_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_puzzle.png b/app/src/main/res/drawable-mdpi/ic_action_puzzle.png deleted file mode 100644 index 71261860..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_puzzle.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_save.png b/app/src/main/res/drawable-mdpi/ic_action_save.png deleted file mode 100644 index 59037c47..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_save.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_save_b.png b/app/src/main/res/drawable-mdpi/ic_action_save_b.png deleted file mode 100644 index 4ba840e2..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_save_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_search.png b/app/src/main/res/drawable-mdpi/ic_action_search.png deleted file mode 100644 index b0127b46..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_search.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_settings.png b/app/src/main/res/drawable-mdpi/ic_action_settings.png deleted file mode 100644 index a79b3eeb..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_action_settings.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_add_location.png b/app/src/main/res/drawable-mdpi/ic_add_location.png deleted file mode 100644 index 4f6e90b6..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_add_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_broken_image.png b/app/src/main/res/drawable-mdpi/ic_broken_image.png deleted file mode 100644 index 0b5500b7..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_broken_image.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_bubble_chart.png b/app/src/main/res/drawable-mdpi/ic_bubble_chart.png deleted file mode 100644 index b3589859..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_bubble_chart.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_developer_mode.png b/app/src/main/res/drawable-mdpi/ic_developer_mode.png deleted file mode 100644 index 25ec6743..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_developer_mode.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_emoticon.png b/app/src/main/res/drawable-mdpi/ic_emoticon.png deleted file mode 100644 index f8e42f43..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_emoticon.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_emoticon_b.png b/app/src/main/res/drawable-mdpi/ic_emoticon_b.png deleted file mode 100644 index c1907699..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_emoticon_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_folder.png b/app/src/main/res/drawable-mdpi/ic_folder.png deleted file mode 100644 index ddf9a2b8..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_folder.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_folder_open.png b/app/src/main/res/drawable-mdpi/ic_folder_open.png deleted file mode 100644 index 93d392a5..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_folder_open.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_gps_fixed.png b/app/src/main/res/drawable-mdpi/ic_gps_fixed.png deleted file mode 100644 index bf843aef..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_gps_fixed.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_gradient.png b/app/src/main/res/drawable-mdpi/ic_gradient.png deleted file mode 100644 index e8270ab7..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_gradient.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_grid_on.png b/app/src/main/res/drawable-mdpi/ic_grid_on.png deleted file mode 100644 index 26be8f6e..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_grid_on.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_inventory.png b/app/src/main/res/drawable-mdpi/ic_inventory.png deleted file mode 100644 index 94a3cebb..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_inventory.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_layers.png b/app/src/main/res/drawable-mdpi/ic_layers.png deleted file mode 100644 index ce0a1d66..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_layers.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_location.png b/app/src/main/res/drawable-mdpi/ic_location.png deleted file mode 100644 index ea09c20c..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_nature_people.png b/app/src/main/res/drawable-mdpi/ic_nature_people.png deleted file mode 100644 index 3bd7331d..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_nature_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_people.png b/app/src/main/res/drawable-mdpi/ic_people.png deleted file mode 100644 index f96ff97c..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_people_outline.png b/app/src/main/res/drawable-mdpi/ic_people_outline.png deleted file mode 100644 index f21b20f4..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_people_outline.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_person.png b/app/src/main/res/drawable-mdpi/ic_person.png deleted file mode 100644 index bf0a0a9b..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_person.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_person_pin_circle.png b/app/src/main/res/drawable-mdpi/ic_person_pin_circle.png deleted file mode 100644 index 7f65e98d..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_person_pin_circle.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_place.png b/app/src/main/res/drawable-mdpi/ic_place.png deleted file mode 100644 index 0eab6f62..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_place.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_player.png b/app/src/main/res/drawable-mdpi/ic_player.png deleted file mode 100644 index bb8eb79c..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_player.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_priority_high.png b/app/src/main/res/drawable-mdpi/ic_priority_high.png deleted file mode 100644 index 6e16c7e6..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_priority_high.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_refresh.png b/app/src/main/res/drawable-mdpi/ic_refresh.png deleted file mode 100644 index 52b28511..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_refresh.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_satellite.png b/app/src/main/res/drawable-mdpi/ic_satellite.png deleted file mode 100644 index d7a874a9..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_satellite.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_settings_brightness.png b/app/src/main/res/drawable-mdpi/ic_settings_brightness.png deleted file mode 100644 index 8959ff56..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_settings_brightness.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_terrain.png b/app/src/main/res/drawable-mdpi/ic_terrain.png deleted file mode 100644 index a50bd547..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_terrain.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_visibility.png b/app/src/main/res/drawable-mdpi/ic_visibility.png deleted file mode 100644 index 77f9881e..00000000 Binary files a/app/src/main/res/drawable-mdpi/ic_visibility.png and /dev/null differ diff --git a/app/src/main/res/drawable-v21/sel_item_flat_layer.xml b/app/src/main/res/drawable-v21/sel_item_flat_layer.xml new file mode 100644 index 00000000..fd29166d --- /dev/null +++ b/app/src/main/res/drawable-v21/sel_item_flat_layer.xml @@ -0,0 +1,17 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/ic_action_arrow_right.png b/app/src/main/res/drawable-xhdpi/ic_action_arrow_right.png deleted file mode 100644 index 8754506f..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_arrow_right.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_compass.png b/app/src/main/res/drawable-xhdpi/ic_action_compass.png deleted file mode 100644 index a898960c..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_compass.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_exit.png b/app/src/main/res/drawable-xhdpi/ic_action_exit.png deleted file mode 100644 index a6c2c626..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_exit.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_filter.png b/app/src/main/res/drawable-xhdpi/ic_action_filter.png deleted file mode 100644 index 8a38718c..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_filter.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_home.png b/app/src/main/res/drawable-xhdpi/ic_action_home.png deleted file mode 100644 index 0da2557a..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_home.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_home_b.png b/app/src/main/res/drawable-xhdpi/ic_action_home_b.png deleted file mode 100644 index 4417d8fc..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_home_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_list.png b/app/src/main/res/drawable-xhdpi/ic_action_list.png deleted file mode 100644 index b82b76a2..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_list.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_map.png b/app/src/main/res/drawable-xhdpi/ic_action_map.png deleted file mode 100644 index b9dfeaf5..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_map.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_map_b.png b/app/src/main/res/drawable-xhdpi/ic_action_map_b.png deleted file mode 100644 index f357cc2f..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_map_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_puzzle.png b/app/src/main/res/drawable-xhdpi/ic_action_puzzle.png deleted file mode 100644 index 074a6bea..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_puzzle.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_save.png b/app/src/main/res/drawable-xhdpi/ic_action_save.png deleted file mode 100644 index d71055b9..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_save.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_save_b.png b/app/src/main/res/drawable-xhdpi/ic_action_save_b.png deleted file mode 100644 index e4edfce6..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_save_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_search.png b/app/src/main/res/drawable-xhdpi/ic_action_search.png deleted file mode 100644 index 565bf1c0..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_search.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_settings.png b/app/src/main/res/drawable-xhdpi/ic_action_settings.png deleted file mode 100644 index ce6d809e..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_action_settings.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_add_location.png b/app/src/main/res/drawable-xhdpi/ic_add_location.png deleted file mode 100644 index 68a65cd2..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_add_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_broken_image.png b/app/src/main/res/drawable-xhdpi/ic_broken_image.png deleted file mode 100644 index ebc326cf..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_broken_image.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_bubble_chart.png b/app/src/main/res/drawable-xhdpi/ic_bubble_chart.png deleted file mode 100644 index 728d9f23..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_bubble_chart.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_developer_mode.png b/app/src/main/res/drawable-xhdpi/ic_developer_mode.png deleted file mode 100644 index 0099487f..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_developer_mode.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_emoticon.png b/app/src/main/res/drawable-xhdpi/ic_emoticon.png deleted file mode 100644 index 8eb98cc0..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_emoticon.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_emoticon_b.png b/app/src/main/res/drawable-xhdpi/ic_emoticon_b.png deleted file mode 100644 index 4095695a..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_emoticon_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_folder.png b/app/src/main/res/drawable-xhdpi/ic_folder.png deleted file mode 100644 index 9d443177..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_folder.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_folder_open.png b/app/src/main/res/drawable-xhdpi/ic_folder_open.png deleted file mode 100644 index fc368ae0..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_folder_open.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_gps_fixed.png b/app/src/main/res/drawable-xhdpi/ic_gps_fixed.png deleted file mode 100644 index c2d95aab..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_gps_fixed.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_gradient.png b/app/src/main/res/drawable-xhdpi/ic_gradient.png deleted file mode 100644 index ebfe3690..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_gradient.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_grid_on.png b/app/src/main/res/drawable-xhdpi/ic_grid_on.png deleted file mode 100644 index 513094a3..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_grid_on.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_inventory.png b/app/src/main/res/drawable-xhdpi/ic_inventory.png deleted file mode 100644 index f3346fcb..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_inventory.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_layers.png b/app/src/main/res/drawable-xhdpi/ic_layers.png deleted file mode 100644 index 068ca079..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_layers.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_location.png b/app/src/main/res/drawable-xhdpi/ic_location.png deleted file mode 100644 index a04ea84c..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_nature_people.png b/app/src/main/res/drawable-xhdpi/ic_nature_people.png deleted file mode 100644 index e4a3189e..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_nature_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_people.png b/app/src/main/res/drawable-xhdpi/ic_people.png deleted file mode 100644 index 3c31252a..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_people_outline.png b/app/src/main/res/drawable-xhdpi/ic_people_outline.png deleted file mode 100644 index 9de962a9..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_people_outline.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_person.png b/app/src/main/res/drawable-xhdpi/ic_person.png deleted file mode 100644 index ae93a3f0..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_person.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_person_pin_circle.png b/app/src/main/res/drawable-xhdpi/ic_person_pin_circle.png deleted file mode 100644 index 8fb27e29..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_person_pin_circle.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_place.png b/app/src/main/res/drawable-xhdpi/ic_place.png deleted file mode 100644 index b21efe74..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_place.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_player.png b/app/src/main/res/drawable-xhdpi/ic_player.png deleted file mode 100644 index d9f5151b..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_player.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_priority_high.png b/app/src/main/res/drawable-xhdpi/ic_priority_high.png deleted file mode 100644 index 775a376f..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_priority_high.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_refresh.png b/app/src/main/res/drawable-xhdpi/ic_refresh.png deleted file mode 100644 index 6d4481ff..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_refresh.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_satellite.png b/app/src/main/res/drawable-xhdpi/ic_satellite.png deleted file mode 100644 index e4ab18d2..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_satellite.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_settings_brightness.png b/app/src/main/res/drawable-xhdpi/ic_settings_brightness.png deleted file mode 100644 index 00bbe1ee..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_settings_brightness.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_terrain.png b/app/src/main/res/drawable-xhdpi/ic_terrain.png deleted file mode 100644 index ca568725..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_terrain.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_visibility.png b/app/src/main/res/drawable-xhdpi/ic_visibility.png deleted file mode 100644 index 8027ea01..00000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_visibility.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_arrow_right.png b/app/src/main/res/drawable-xxhdpi/ic_action_arrow_right.png deleted file mode 100644 index be62f58d..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_arrow_right.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_compass.png b/app/src/main/res/drawable-xxhdpi/ic_action_compass.png deleted file mode 100644 index 2e6094b0..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_compass.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_exit.png b/app/src/main/res/drawable-xxhdpi/ic_action_exit.png deleted file mode 100644 index 85c41bfa..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_exit.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_filter.png b/app/src/main/res/drawable-xxhdpi/ic_action_filter.png deleted file mode 100644 index 105aeb87..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_filter.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_home.png b/app/src/main/res/drawable-xxhdpi/ic_action_home.png deleted file mode 100644 index 34b925fe..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_home.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_home_b.png b/app/src/main/res/drawable-xxhdpi/ic_action_home_b.png deleted file mode 100644 index 378a25f4..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_home_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_list.png b/app/src/main/res/drawable-xxhdpi/ic_action_list.png deleted file mode 100644 index cfc2e129..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_list.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_map.png b/app/src/main/res/drawable-xxhdpi/ic_action_map.png deleted file mode 100644 index 8c379b0d..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_map.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_map_b.png b/app/src/main/res/drawable-xxhdpi/ic_action_map_b.png deleted file mode 100644 index c431e66f..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_map_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_puzzle.png b/app/src/main/res/drawable-xxhdpi/ic_action_puzzle.png deleted file mode 100644 index 1d6404e7..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_puzzle.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_save.png b/app/src/main/res/drawable-xxhdpi/ic_action_save.png deleted file mode 100644 index 272e2b67..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_save.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_save_b.png b/app/src/main/res/drawable-xxhdpi/ic_action_save_b.png deleted file mode 100644 index 3ede5aa3..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_save_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_search.png b/app/src/main/res/drawable-xxhdpi/ic_action_search.png deleted file mode 100644 index dab65748..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_search.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_settings.png b/app/src/main/res/drawable-xxhdpi/ic_action_settings.png deleted file mode 100644 index fa688070..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_action_settings.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_add_location.png b/app/src/main/res/drawable-xxhdpi/ic_add_location.png deleted file mode 100644 index e447a33b..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_add_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_broken_image.png b/app/src/main/res/drawable-xxhdpi/ic_broken_image.png deleted file mode 100644 index 6e43d542..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_broken_image.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_bubble_chart.png b/app/src/main/res/drawable-xxhdpi/ic_bubble_chart.png deleted file mode 100644 index 81a9f543..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_bubble_chart.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_developer_mode.png b/app/src/main/res/drawable-xxhdpi/ic_developer_mode.png deleted file mode 100644 index d0e74a90..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_developer_mode.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_emoticon.png b/app/src/main/res/drawable-xxhdpi/ic_emoticon.png deleted file mode 100644 index 872afdf7..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_emoticon.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_emoticon_b.png b/app/src/main/res/drawable-xxhdpi/ic_emoticon_b.png deleted file mode 100644 index e38b00e8..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_emoticon_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_folder.png b/app/src/main/res/drawable-xxhdpi/ic_folder.png deleted file mode 100644 index 5f6849d9..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_folder.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_folder_open.png b/app/src/main/res/drawable-xxhdpi/ic_folder_open.png deleted file mode 100644 index 2b4080b3..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_folder_open.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_gps_fixed.png b/app/src/main/res/drawable-xxhdpi/ic_gps_fixed.png deleted file mode 100644 index 9eaa5c24..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_gps_fixed.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_gradient.png b/app/src/main/res/drawable-xxhdpi/ic_gradient.png deleted file mode 100644 index 935aa3e7..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_gradient.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_grid_on.png b/app/src/main/res/drawable-xxhdpi/ic_grid_on.png deleted file mode 100644 index da4bb8ef..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_grid_on.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_inventory.png b/app/src/main/res/drawable-xxhdpi/ic_inventory.png deleted file mode 100644 index c68ec1af..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_inventory.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_layers.png b/app/src/main/res/drawable-xxhdpi/ic_layers.png deleted file mode 100644 index 35f9641c..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_layers.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_location.png b/app/src/main/res/drawable-xxhdpi/ic_location.png deleted file mode 100644 index b910fa7e..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_nature_people.png b/app/src/main/res/drawable-xxhdpi/ic_nature_people.png deleted file mode 100644 index a4a92605..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_nature_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_people.png b/app/src/main/res/drawable-xxhdpi/ic_people.png deleted file mode 100644 index 178fb0f9..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_people_outline.png b/app/src/main/res/drawable-xxhdpi/ic_people_outline.png deleted file mode 100644 index 61fd11b7..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_people_outline.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_person.png b/app/src/main/res/drawable-xxhdpi/ic_person.png deleted file mode 100644 index 17739498..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_person.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_person_pin_circle.png b/app/src/main/res/drawable-xxhdpi/ic_person_pin_circle.png deleted file mode 100644 index 531f52c2..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_person_pin_circle.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_place.png b/app/src/main/res/drawable-xxhdpi/ic_place.png deleted file mode 100644 index 96274de7..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_place.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_player.png b/app/src/main/res/drawable-xxhdpi/ic_player.png deleted file mode 100644 index 512bb670..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_player.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_priority_high.png b/app/src/main/res/drawable-xxhdpi/ic_priority_high.png deleted file mode 100644 index cd331e9e..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_priority_high.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_refresh.png b/app/src/main/res/drawable-xxhdpi/ic_refresh.png deleted file mode 100644 index f65e33f7..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_refresh.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_satellite.png b/app/src/main/res/drawable-xxhdpi/ic_satellite.png deleted file mode 100644 index 2eeae828..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_satellite.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_settings_brightness.png b/app/src/main/res/drawable-xxhdpi/ic_settings_brightness.png deleted file mode 100644 index d1b1e8d5..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_settings_brightness.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_terrain.png b/app/src/main/res/drawable-xxhdpi/ic_terrain.png deleted file mode 100644 index a3ba2b30..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_terrain.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_visibility.png b/app/src/main/res/drawable-xxhdpi/ic_visibility.png deleted file mode 100644 index 89bfc0f0..00000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_visibility.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_arrow_right.png b/app/src/main/res/drawable-xxxhdpi/ic_action_arrow_right.png deleted file mode 100644 index 7141d106..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_arrow_right.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_compass.png b/app/src/main/res/drawable-xxxhdpi/ic_action_compass.png deleted file mode 100644 index 6b655b7a..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_compass.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_exit.png b/app/src/main/res/drawable-xxxhdpi/ic_action_exit.png deleted file mode 100644 index 11ff926d..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_exit.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_filter.png b/app/src/main/res/drawable-xxxhdpi/ic_action_filter.png deleted file mode 100644 index 502a25c9..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_filter.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_home.png b/app/src/main/res/drawable-xxxhdpi/ic_action_home.png deleted file mode 100644 index 7d06055e..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_home.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_home_b.png b/app/src/main/res/drawable-xxxhdpi/ic_action_home_b.png deleted file mode 100644 index 2ff62077..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_home_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_list.png b/app/src/main/res/drawable-xxxhdpi/ic_action_list.png deleted file mode 100644 index cddbeb4f..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_list.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_map.png b/app/src/main/res/drawable-xxxhdpi/ic_action_map.png deleted file mode 100644 index a18b2c53..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_map.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_map_b.png b/app/src/main/res/drawable-xxxhdpi/ic_action_map_b.png deleted file mode 100644 index 6ed462d7..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_map_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_puzzle.png b/app/src/main/res/drawable-xxxhdpi/ic_action_puzzle.png deleted file mode 100644 index 81951bd3..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_puzzle.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_save.png b/app/src/main/res/drawable-xxxhdpi/ic_action_save.png deleted file mode 100644 index efe6b14f..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_save.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_save_b.png b/app/src/main/res/drawable-xxxhdpi/ic_action_save_b.png deleted file mode 100644 index abc8499c..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_save_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_search.png b/app/src/main/res/drawable-xxxhdpi/ic_action_search.png deleted file mode 100644 index c461e244..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_search.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png b/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png deleted file mode 100644 index a1168939..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_add_location.png b/app/src/main/res/drawable-xxxhdpi/ic_add_location.png deleted file mode 100644 index 5f540f42..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_add_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_broken_image.png b/app/src/main/res/drawable-xxxhdpi/ic_broken_image.png deleted file mode 100644 index 68c4b97c..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_broken_image.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_bubble_chart.png b/app/src/main/res/drawable-xxxhdpi/ic_bubble_chart.png deleted file mode 100644 index f6ec6a56..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_bubble_chart.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_developer_mode.png b/app/src/main/res/drawable-xxxhdpi/ic_developer_mode.png deleted file mode 100644 index d01db080..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_developer_mode.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_emoticon.png b/app/src/main/res/drawable-xxxhdpi/ic_emoticon.png deleted file mode 100644 index 1597b695..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_emoticon.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_emoticon_b.png b/app/src/main/res/drawable-xxxhdpi/ic_emoticon_b.png deleted file mode 100644 index 2287afb0..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_emoticon_b.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_folder.png b/app/src/main/res/drawable-xxxhdpi/ic_folder.png deleted file mode 100644 index 16e9e093..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_folder.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_folder_open.png b/app/src/main/res/drawable-xxxhdpi/ic_folder_open.png deleted file mode 100644 index a14d8952..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_folder_open.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_gps_fixed.png b/app/src/main/res/drawable-xxxhdpi/ic_gps_fixed.png deleted file mode 100644 index 7f588a26..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_gps_fixed.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_gradient.png b/app/src/main/res/drawable-xxxhdpi/ic_gradient.png deleted file mode 100644 index eb683c1a..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_gradient.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_grid_on.png b/app/src/main/res/drawable-xxxhdpi/ic_grid_on.png deleted file mode 100644 index a8c41f3e..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_grid_on.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_inventory.png b/app/src/main/res/drawable-xxxhdpi/ic_inventory.png deleted file mode 100644 index 43be3f25..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_inventory.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_layers.png b/app/src/main/res/drawable-xxxhdpi/ic_layers.png deleted file mode 100644 index 2fde17c5..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_layers.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_location.png b/app/src/main/res/drawable-xxxhdpi/ic_location.png deleted file mode 100644 index c6bdce60..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_location.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_nature_people.png b/app/src/main/res/drawable-xxxhdpi/ic_nature_people.png deleted file mode 100644 index 7470ff1a..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_nature_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_people.png b/app/src/main/res/drawable-xxxhdpi/ic_people.png deleted file mode 100644 index 911c4b52..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_people.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_people_outline.png b/app/src/main/res/drawable-xxxhdpi/ic_people_outline.png deleted file mode 100644 index e57ae0fc..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_people_outline.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_person.png b/app/src/main/res/drawable-xxxhdpi/ic_person.png deleted file mode 100644 index c1e75b4d..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_person.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_person_pin_circle.png b/app/src/main/res/drawable-xxxhdpi/ic_person_pin_circle.png deleted file mode 100644 index 5c83a95e..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_person_pin_circle.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_place.png b/app/src/main/res/drawable-xxxhdpi/ic_place.png deleted file mode 100644 index ba0538e1..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_place.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_player.png b/app/src/main/res/drawable-xxxhdpi/ic_player.png deleted file mode 100644 index e7398b08..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_player.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_priority_high.png b/app/src/main/res/drawable-xxxhdpi/ic_priority_high.png deleted file mode 100644 index fc335f4c..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_priority_high.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_refresh.png b/app/src/main/res/drawable-xxxhdpi/ic_refresh.png deleted file mode 100644 index 455000ed..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_refresh.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_satellite.png b/app/src/main/res/drawable-xxxhdpi/ic_satellite.png deleted file mode 100644 index fdcdfb31..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_satellite.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_settings_brightness.png b/app/src/main/res/drawable-xxxhdpi/ic_settings_brightness.png deleted file mode 100644 index c7f9f208..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_settings_brightness.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_terrain.png b/app/src/main/res/drawable-xxxhdpi/ic_terrain.png deleted file mode 100644 index 347669d1..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_terrain.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_visibility.png b/app/src/main/res/drawable-xxxhdpi/ic_visibility.png deleted file mode 100644 index 5aa86dec..00000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_visibility.png and /dev/null differ diff --git a/app/src/main/res/drawable/bg_dialog_transparent.xml b/app/src/main/res/drawable/bg_dialog_transparent.xml new file mode 100644 index 00000000..ef02075d --- /dev/null +++ b/app/src/main/res/drawable/bg_dialog_transparent.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_fab_transparent.xml b/app/src/main/res/drawable/bg_fab_transparent.xml new file mode 100644 index 00000000..3b878a13 --- /dev/null +++ b/app/src/main/res/drawable/bg_fab_transparent.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_float_transparent.xml b/app/src/main/res/drawable/bg_float_transparent.xml new file mode 100644 index 00000000..bf4e94f3 --- /dev/null +++ b/app/src/main/res/drawable/bg_float_transparent.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/external.png b/app/src/main/res/drawable/external.png new file mode 100644 index 00000000..45fba9e8 Binary files /dev/null and b/app/src/main/res/drawable/external.png differ diff --git a/app/src/main/res/drawable/ic_action_arrow_right.xml b/app/src/main/res/drawable/ic_action_arrow_right.xml new file mode 100644 index 00000000..f8f4650c --- /dev/null +++ b/app/src/main/res/drawable/ic_action_arrow_right.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_close.xml b/app/src/main/res/drawable/ic_action_close.xml new file mode 100644 index 00000000..914246e2 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_close.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_exit.xml b/app/src/main/res/drawable/ic_action_exit.xml new file mode 100644 index 00000000..2c3b9778 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_exit.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_filter.xml b/app/src/main/res/drawable/ic_action_filter.xml new file mode 100644 index 00000000..41a72184 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_filter.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_home.xml b/app/src/main/res/drawable/ic_action_home.xml new file mode 100644 index 00000000..98ee1341 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_home.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_home_b.xml b/app/src/main/res/drawable/ic_action_home_b.xml new file mode 100644 index 00000000..8e5a6fb8 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_home_b.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_list.xml b/app/src/main/res/drawable/ic_action_list.xml new file mode 100644 index 00000000..e29491cc --- /dev/null +++ b/app/src/main/res/drawable/ic_action_list.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_map.xml b/app/src/main/res/drawable/ic_action_map.xml new file mode 100644 index 00000000..fbe75e9e --- /dev/null +++ b/app/src/main/res/drawable/ic_action_map.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_map_b.xml b/app/src/main/res/drawable/ic_action_map_b.xml new file mode 100644 index 00000000..ec0acbb1 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_map_b.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_puzzle.xml b/app/src/main/res/drawable/ic_action_puzzle.xml new file mode 100644 index 00000000..85ea9e69 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_puzzle.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_save.xml b/app/src/main/res/drawable/ic_action_save.xml new file mode 100644 index 00000000..5ed3c6e3 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_save.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_save_b.xml b/app/src/main/res/drawable/ic_action_save_b.xml new file mode 100644 index 00000000..19d1ecb8 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_save_b.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_search.xml b/app/src/main/res/drawable/ic_action_search.xml new file mode 100644 index 00000000..fd21d7c0 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_search.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_search_black.xml b/app/src/main/res/drawable/ic_action_search_black.xml new file mode 100644 index 00000000..4b467960 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_search_black.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_action_settings.xml b/app/src/main/res/drawable/ic_action_settings.xml new file mode 100644 index 00000000..601bcb51 --- /dev/null +++ b/app/src/main/res/drawable/ic_action_settings.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 00000000..834ff462 --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_add_black.xml b/app/src/main/res/drawable/ic_add_black.xml new file mode 100644 index 00000000..dd959826 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_black.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_broken_image.xml b/app/src/main/res/drawable/ic_broken_image.xml new file mode 100644 index 00000000..42a12c08 --- /dev/null +++ b/app/src/main/res/drawable/ic_broken_image.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_bubble_chart.xml b/app/src/main/res/drawable/ic_bubble_chart.xml new file mode 100644 index 00000000..13c627cc --- /dev/null +++ b/app/src/main/res/drawable/ic_bubble_chart.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_emoticon.xml b/app/src/main/res/drawable/ic_emoticon.xml new file mode 100644 index 00000000..2a1d9034 --- /dev/null +++ b/app/src/main/res/drawable/ic_emoticon.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_folder_open.xml b/app/src/main/res/drawable/ic_folder_open.xml new file mode 100644 index 00000000..559c7e36 --- /dev/null +++ b/app/src/main/res/drawable/ic_folder_open.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_gps_fixed.xml b/app/src/main/res/drawable/ic_gps_fixed.xml new file mode 100644 index 00000000..ca15beab --- /dev/null +++ b/app/src/main/res/drawable/ic_gps_fixed.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_gradient.xml b/app/src/main/res/drawable/ic_gradient.xml new file mode 100644 index 00000000..1f77438a --- /dev/null +++ b/app/src/main/res/drawable/ic_gradient.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_grid_on.xml b/app/src/main/res/drawable/ic_grid_on.xml new file mode 100644 index 00000000..12dbc651 --- /dev/null +++ b/app/src/main/res/drawable/ic_grid_on.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_help_black.xml b/app/src/main/res/drawable/ic_help_black.xml new file mode 100644 index 00000000..b0af2467 --- /dev/null +++ b/app/src/main/res/drawable/ic_help_black.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_inventory.xml b/app/src/main/res/drawable/ic_inventory.xml new file mode 100644 index 00000000..7d164a0e --- /dev/null +++ b/app/src/main/res/drawable/ic_inventory.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..0d60f2b8 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..90570271 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_layers.xml b/app/src/main/res/drawable/ic_layers.xml new file mode 100644 index 00000000..a99b97cd --- /dev/null +++ b/app/src/main/res/drawable/ic_layers.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_location.xml b/app/src/main/res/drawable/ic_location.xml new file mode 100644 index 00000000..c2521a2e --- /dev/null +++ b/app/src/main/res/drawable/ic_location.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_menu_camera.xml b/app/src/main/res/drawable/ic_menu_camera.xml similarity index 75% rename from app/src/main/res/drawable-v21/ic_menu_camera.xml rename to app/src/main/res/drawable/ic_menu_camera.xml index 0d9ea104..6b1b8e21 100644 --- a/app/src/main/res/drawable-v21/ic_menu_camera.xml +++ b/app/src/main/res/drawable/ic_menu_camera.xml @@ -1,12 +1,12 @@ + android:viewportWidth="24.0" + android:viewportHeight="24.0"> diff --git a/app/src/main/res/drawable/ic_menu_camera_black.xml b/app/src/main/res/drawable/ic_menu_camera_black.xml new file mode 100644 index 00000000..634fe922 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_camera_black.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable-v21/ic_menu_gallery.xml b/app/src/main/res/drawable/ic_menu_gallery.xml similarity index 100% rename from app/src/main/res/drawable-v21/ic_menu_gallery.xml rename to app/src/main/res/drawable/ic_menu_gallery.xml diff --git a/app/src/main/res/drawable-v21/ic_menu_manage.xml b/app/src/main/res/drawable/ic_menu_manage.xml similarity index 100% rename from app/src/main/res/drawable-v21/ic_menu_manage.xml rename to app/src/main/res/drawable/ic_menu_manage.xml diff --git a/app/src/main/res/drawable-v21/ic_menu_send.xml b/app/src/main/res/drawable/ic_menu_send.xml similarity index 100% rename from app/src/main/res/drawable-v21/ic_menu_send.xml rename to app/src/main/res/drawable/ic_menu_send.xml diff --git a/app/src/main/res/drawable-v21/ic_menu_share.xml b/app/src/main/res/drawable/ic_menu_share.xml similarity index 100% rename from app/src/main/res/drawable-v21/ic_menu_share.xml rename to app/src/main/res/drawable/ic_menu_share.xml diff --git a/app/src/main/res/drawable-v21/ic_menu_slideshow.xml b/app/src/main/res/drawable/ic_menu_slideshow.xml similarity index 100% rename from app/src/main/res/drawable-v21/ic_menu_slideshow.xml rename to app/src/main/res/drawable/ic_menu_slideshow.xml diff --git a/app/src/main/res/drawable/ic_people.xml b/app/src/main/res/drawable/ic_people.xml new file mode 100644 index 00000000..8982c5c1 --- /dev/null +++ b/app/src/main/res/drawable/ic_people.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_people_outline.xml b/app/src/main/res/drawable/ic_people_outline.xml new file mode 100644 index 00000000..f6930229 --- /dev/null +++ b/app/src/main/res/drawable/ic_people_outline.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_person.xml b/app/src/main/res/drawable/ic_person.xml new file mode 100644 index 00000000..38765cc9 --- /dev/null +++ b/app/src/main/res/drawable/ic_person.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_person_black.xml b/app/src/main/res/drawable/ic_person_black.xml new file mode 100644 index 00000000..eb96cc22 --- /dev/null +++ b/app/src/main/res/drawable/ic_person_black.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_place.xml b/app/src/main/res/drawable/ic_place.xml new file mode 100644 index 00000000..8d8f3cb4 --- /dev/null +++ b/app/src/main/res/drawable/ic_place.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_satellite.xml b/app/src/main/res/drawable/ic_satellite.xml new file mode 100644 index 00000000..0478dedf --- /dev/null +++ b/app/src/main/res/drawable/ic_satellite.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_selection_extend.xml b/app/src/main/res/drawable/ic_selection_extend.xml new file mode 100644 index 00000000..bfe99df1 --- /dev/null +++ b/app/src/main/res/drawable/ic_selection_extend.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_settings_brightness.xml b/app/src/main/res/drawable/ic_settings_brightness.xml new file mode 100644 index 00000000..0cba5200 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_brightness.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_tag_byte.xml b/app/src/main/res/drawable/ic_tag_byte.xml new file mode 100644 index 00000000..c657028c --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_byte.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_byte_array.xml b/app/src/main/res/drawable/ic_tag_byte_array.xml new file mode 100644 index 00000000..ff3d4535 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_byte_array.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_compound.xml b/app/src/main/res/drawable/ic_tag_compound.xml new file mode 100644 index 00000000..3a312a97 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_compound.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_default.xml b/app/src/main/res/drawable/ic_tag_default.xml new file mode 100644 index 00000000..09219470 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_default.xml @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_double.xml b/app/src/main/res/drawable/ic_tag_double.xml new file mode 100644 index 00000000..3b77336e --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_double.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_float.xml b/app/src/main/res/drawable/ic_tag_float.xml new file mode 100644 index 00000000..848f1845 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_float.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_tag_int.xml b/app/src/main/res/drawable/ic_tag_int.xml new file mode 100644 index 00000000..cc0a8d88 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_int.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_tag_int_array.xml b/app/src/main/res/drawable/ic_tag_int_array.xml new file mode 100644 index 00000000..bcc6932f --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_int_array.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_list.xml b/app/src/main/res/drawable/ic_tag_list.xml new file mode 100644 index 00000000..37c764a4 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_list.xml @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_long.xml b/app/src/main/res/drawable/ic_tag_long.xml new file mode 100644 index 00000000..fb309af9 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_long.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_tag_root.xml b/app/src/main/res/drawable/ic_tag_root.xml new file mode 100644 index 00000000..b2047d75 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_root.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_short.xml b/app/src/main/res/drawable/ic_tag_short.xml new file mode 100644 index 00000000..3b8b699f --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_short.xml @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_tag_string.xml b/app/src/main/res/drawable/ic_tag_string.xml new file mode 100644 index 00000000..528f1857 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_string.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_terrain.xml b/app/src/main/res/drawable/ic_terrain.xml new file mode 100644 index 00000000..50b23a99 --- /dev/null +++ b/app/src/main/res/drawable/ic_terrain.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_visibility.xml b/app/src/main/res/drawable/ic_visibility.xml new file mode 100644 index 00000000..ff446d49 --- /dev/null +++ b/app/src/main/res/drawable/ic_visibility.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_world_icon.xml b/app/src/main/res/drawable/ic_world_icon.xml new file mode 100644 index 00000000..4f949a27 --- /dev/null +++ b/app/src/main/res/drawable/ic_world_icon.xml @@ -0,0 +1,274 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/lampshade.png b/app/src/main/res/drawable/lampshade.png new file mode 100644 index 00000000..840616ed Binary files /dev/null and b/app/src/main/res/drawable/lampshade.png differ diff --git a/app/src/main/res/drawable/rect_border_round_corner.xml b/app/src/main/res/drawable/rect_border_round_corner.xml new file mode 100644 index 00000000..421c7ce3 --- /dev/null +++ b/app/src/main/res/drawable/rect_border_round_corner.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/sel_item_flat_layer.xml b/app/src/main/res/drawable/sel_item_flat_layer.xml new file mode 100644 index 00000000..9c1df3da --- /dev/null +++ b/app/src/main/res/drawable/sel_item_flat_layer.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/sel_wid_mcbtn_bg.xml b/app/src/main/res/drawable/sel_wid_mcbtn_bg.xml new file mode 100644 index 00000000..0f145b86 --- /dev/null +++ b/app/src/main/res/drawable/sel_wid_mcbtn_bg.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/wid_mcbtn_clicked.9.png b/app/src/main/res/drawable/wid_mcbtn_clicked.9.png new file mode 100644 index 00000000..df14d887 Binary files /dev/null and b/app/src/main/res/drawable/wid_mcbtn_clicked.9.png differ diff --git a/app/src/main/res/drawable/wid_mcbtn_default.9.png b/app/src/main/res/drawable/wid_mcbtn_default.9.png new file mode 100644 index 00000000..c35f579b Binary files /dev/null and b/app/src/main/res/drawable/wid_mcbtn_default.9.png differ diff --git a/app/src/main/res/drawable/wid_mcbtn_disabled.9.png b/app/src/main/res/drawable/wid_mcbtn_disabled.9.png new file mode 100644 index 00000000..a79aa526 Binary files /dev/null and b/app/src/main/res/drawable/wid_mcbtn_disabled.9.png differ diff --git a/app/src/main/res/drawable/wid_mcsinglesel_checked.9.png b/app/src/main/res/drawable/wid_mcsinglesel_checked.9.png new file mode 100644 index 00000000..1e4e0b56 Binary files /dev/null and b/app/src/main/res/drawable/wid_mcsinglesel_checked.9.png differ diff --git a/app/src/main/res/layout-port/frag_map_goto.xml b/app/src/main/res/layout-port/frag_map_goto.xml new file mode 100644 index 00000000..9a42b99a --- /dev/null +++ b/app/src/main/res/layout-port/frag_map_goto.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-port/frag_sel_menu.xml b/app/src/main/res/layout-port/frag_sel_menu.xml new file mode 100644 index 00000000..7ce04d3d --- /dev/null +++ b/app/src/main/res/layout-port/frag_sel_menu.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w900dp/worlditem_list.xml b/app/src/main/res/layout-w900dp/worlditem_list.xml index 3409611a..f0dd3d0b 100644 --- a/app/src/main/res/layout-w900dp/worlditem_list.xml +++ b/app/src/main/res/layout-w900dp/worlditem_list.xml @@ -17,7 +17,7 @@ --> - + + + + + + + + + + + + + + +