Skip to content

Commit

Permalink
get and book commands, head quick breaking, MSD complete restructure,…
Browse files Browse the repository at this point in the history
… code cleanup
  • Loading branch information
KruASe76 committed May 28, 2023
1 parent 3dcbe34 commit 947c36a
Show file tree
Hide file tree
Showing 24 changed files with 1,149 additions and 624 deletions.
41 changes: 22 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
# mine-nopoly
# MineNopoly

![](https://img.shields.io/badge/MINECRAFT-1.16.3+-966C4A?style=for-the-badge&labelColor=53AC56)
![](https://img.shields.io/badge/MINECRAFT-1.16.5+-966C4A?style=for-the-badge&labelColor=53AC56)
![](https://img.shields.io/badge/JAVA-1.8+-5283A2?style=for-the-badge&labelColor=E86F00)

A Spigot (Bukkit) Minecraft plugin that implements automated Monopoly bank into the game.


## Features [WIP]
## Features

- [x] Monopoly bank functionality using a `chest`, `barrel` or any `shulker_box` in which game money items are placed and removed from
- [x] US, UK and RU localizations support
- [x] Player balance tracking using a scoreboard
- [ ] _Chance_ and _Community chest_ cards randomization
- [x] _Houses_ implementation using sea pickles (can be placed up to four in a single block)
- [x] _Hotels_ lantern blocks immediate breaking without tools
- [ ] A book with links to get game items and a list and descriptions of all game properties
- [x] Built-in dice randomizer
- [x] Monopoly bank block breaking protection; game items consuming/placement protection
- [x] Anti-counterfeiting game money items (default: `flint`, `coal`, `quartz`, `lapis_lazuli`, `iron_nugget`, `gold_nugget`, `emerald`) protection via [NBT data](https://minecraft.fandom.com/wiki/NBT_format)
- Monopoly bank functionality using a `chest`, `barrel` or any `shulker_box` in which game items are placed and removed from
- US, UK and RU game localizations support
- Player balance tracking using a scoreboard
- _Chance_ and _Community chest_ cards randomization
- _Houses_ implementation using `sea_pickles` (can be placed up to four in a single block)
- _Hotels_ `lantern` blocks immediate breaking without tools
- `player_head` blocks immediate breaking (assumed to be tokens)
- A book with links to get game items and a list and descriptions of all game properties
- Built-in dice randomizer
- Bank block breaking protection; game items consuming/placement protection
- Anti-counterfeiting game items protection via [NBT data](https://minecraft.fandom.com/wiki/NBT_format)


## Usage

### How to play?emptyList
### How to play?

You just build a playing field, place a chest (can also be a barrel or a shulker box) somewhere and call `/mp start <chest coordinates>`!
To get and remove game items use [chat entries](#valid-in-game-chat-entries) and the book you can get via `/mp book <language>`.
To get and remove game items use [chat entries](#valid-in-game-chat-entries) and the book you can get via `/mp book <localization>`.
_Houses_ and _Hotels_ are meant to be placed on street cells; all other items are meant not to be used in any way except keeping in the inventory and transferring between the players.
To finish the game return all the game items to the bank (and type `--` to remove them) and call `/mp finish`; if you can't return them one of the server operators (by default) should call `/mp finish forced`.

### Commands

`/monopoly` is the main plugin command, which has the alias `/mp`.
`/minenopoly` is the main plugin command, which has the alias `/mp`.

| Command | Description |
|----------------------|------------------------------------------------------------------------------|
Expand All @@ -57,8 +58,8 @@ _Note:_ Only available during the game.

## Configuration ([default](/src/main/resources/config.yml))

- Game items (it is also possible to specify denominations for money)
- Plugin messages [WIP]
- Game money items (also their denominations)
- Plugin messages
- info
- error
- help
Expand All @@ -80,7 +81,7 @@ _Note:_ Only available during the game.

## Game field

Here is a [litematica](https://github.com/KruASe76/mine-nopoly/raw/main/additions/Monopoly_Field.litematic) of the game field designed by me, however, you can build your own!
Here is a [litematica](https://github.com/KruASe76/MineNopoly/raw/main/additions/field.litematic) of the game field designed by me, however, you can always build your own!


## Reference
Expand All @@ -90,6 +91,8 @@ Here is a [litematica](https://github.com/KruASe76/mine-nopoly/raw/main/addition
- Some code
- [Monopoly Wiki](https://monopoly.fandom.com/wiki/Main_Page)
- Property names, _Chance_ and _Community chest_ cards for US and UK editions
- [Wikibooks (Monopoly properties reference)](https://en.wikibooks.org/wiki/Monopoly/Properties_reference)
- Property costs and rents


## Special thanks to:
Expand Down
Binary file added additions/field.litematic
Binary file not shown.
12 changes: 6 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
<modelVersion>4.0.0</modelVersion>

<groupId>me.kruase</groupId>
<artifactId>mine-nopoly</artifactId>
<version>0.6</version>
<artifactId>MineNopoly</artifactId>
<version>1.0</version>
<packaging>jar</packaging>

<name>mine-nopoly</name>
<name>MineNopoly</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<kotlin.version>1.8.20</kotlin.version>
<mcApi.version>1.16.3</mcApi.version>
<kotlin.version>1.8.21</kotlin.version>
<mcApi.version>1.16</mcApi.version>
</properties>

<build>
Expand Down Expand Up @@ -78,7 +78,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${mcApi.version}-R0.1-SNAPSHOT</version>
<version>1.16.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/me/kruase/minenopoly/Minenopoly.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package me.kruase.minenopoly

import me.kruase.minenopoly.util.isInGame
import org.bukkit.plugin.java.JavaPlugin
import org.bukkit.scoreboard.Scoreboard
import org.bukkit.ChatColor
import me.kruase.minenopoly.util.isInGame
import net.md_5.bungee.api.ChatColor as CC


class Minenopoly : JavaPlugin() {
Expand All @@ -18,7 +18,7 @@ class Minenopoly : JavaPlugin() {
if (message == null) return
instance.server.onlinePlayers.forEach {
it.sendMessage(
"${ChatColor.GOLD}[${ChatColor.GREEN}MineNopoly${ChatColor.GOLD}]${ChatColor.RESET} $message"
"${CC.GOLD}[${CC.GREEN}${instance.name}${CC.GOLD}]${CC.RESET} $message"
)
}
}
Expand All @@ -27,7 +27,7 @@ class Minenopoly : JavaPlugin() {
if (message == null) return
instance.server.onlinePlayers.filter { it.isInGame() }.forEach {
it.sendMessage(
"${ChatColor.GOLD}[${ChatColor.GREEN}MineNopoly${ChatColor.GOLD}]${ChatColor.RESET} $message"
"${CC.GOLD}[${CC.GREEN}${instance.name}${CC.GOLD}]${CC.RESET} $message"
)
}
}
Expand All @@ -38,7 +38,7 @@ class Minenopoly : JavaPlugin() {
userConfig = getUserConfig()
scoreboard = MinenopolyScoreboard.new(server)

getCommand("monopoly")!!.setExecutor(MinenopolyCommands())
getCommand("minenopoly")!!.setExecutor(MinenopolyCommands())

server.pluginManager.registerEvents(MinenopolyEvents(), instance)
}
Expand Down
25 changes: 12 additions & 13 deletions src/main/kotlin/me/kruase/minenopoly/MinenopolyCommands.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package me.kruase.minenopoly

import org.bukkit.command.TabExecutor
import org.bukkit.command.CommandSender
import org.bukkit.command.Command
import org.bukkit.entity.Player
import org.bukkit.ChatColor
import me.kruase.minenopoly.commands.*
import me.kruase.minenopoly.util.hasPluginPermission
import org.bukkit.command.Command
import org.bukkit.command.CommandSender
import org.bukkit.command.TabExecutor
import org.bukkit.entity.Player
import net.md_5.bungee.api.ChatColor as CC


private val playerOnlyCommands = setOf("start", "book", "get")
Expand All @@ -24,7 +24,7 @@ class MinenopolyCommands : TabExecutor {
null -> Minenopoly.userConfig.messages.help.keys
.filter {
sender.hasPluginPermission(it.replace("-", "."))
} - "header" - "finish-forced" - if (sender !is Player) emptySet() else playerOnlyCommands
} - "header" - "finish-forced" - if (sender is Player) emptySet() else playerOnlyCommands
"help" -> when {
sender.hasPluginPermission("help") -> when (fullArgs.getOrNull(1)) {
null -> Minenopoly.userConfig.messages.help.keys
Expand Down Expand Up @@ -60,7 +60,7 @@ class MinenopolyCommands : TabExecutor {
is Player -> when (fullArgs.getOrNull(1)) {
null -> listOf("us", "uk", "ru")
"us", "uk", "ru" -> when (fullArgs.getOrNull(2)) {
null -> listOf("chance", "community_chest", "property", "house", "hotel")
null -> listOf("chance", "community_chest", "house", "hotel", "property")
"property" -> when (fullArgs.getOrNull(3)) {
null -> listOf("street", "railroad", "utility")
"street" -> when (fullArgs.getOrNull(4)) {
Expand All @@ -80,7 +80,7 @@ class MinenopolyCommands : TabExecutor {
else -> emptyList()
}
"utility" -> when (fullArgs.getOrNull(4)) {
null -> listOf("electric", "water")
null -> listOf("electricity", "water")
else -> emptyList()
}
else -> emptyList()
Expand Down Expand Up @@ -113,15 +113,14 @@ class MinenopolyCommands : TabExecutor {
}
} catch (e: UnsupportedOperationException) {
sender.sendMessage(
"${ChatColor.RED}${Minenopoly.userConfig.messages.error["no-permission"] ?: "Error: no-permission"}"
"${CC.RED}${Minenopoly.userConfig.messages.error["no-permission"] ?: "Error: no-permission"}"
)
} catch (e: IllegalArgumentException) {
sender.sendMessage(
"${ChatColor.RED}${Minenopoly.userConfig.messages.error["invalid-command"] ?: "Error: invalid-command"}"
"${CC.RED}${Minenopoly.userConfig.messages.error["invalid-command"] ?: "Error: invalid-command"}"
)
} catch (e: IllegalStateException) {
// "Unknown error" should never happen
sender.sendMessage("${ChatColor.RED}${e.message ?: "Unknown error"}")
sender.sendMessage("${CC.RED}${e.message ?: "Unknown error"}") // "Unknown error" should never be output
}

return true
Expand All @@ -131,7 +130,7 @@ class MinenopolyCommands : TabExecutor {
when (sender) {
is Player -> command(sender, args)
else -> sender.sendMessage(
"${ChatColor.RED}${Minenopoly.userConfig.messages.error["player-only"] ?: "Error: player-only"}"
"${CC.RED}${Minenopoly.userConfig.messages.error["player-only"] ?: "Error: player-only"}"
)
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/me/kruase/minenopoly/MinenopolyConfig.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package me.kruase.minenopoly

import java.io.File
import org.bukkit.configuration.file.FileConfiguration
import org.bukkit.Material
import org.bukkit.configuration.file.FileConfiguration
import java.io.File


data class MinenopolyConfig(private val config: FileConfiguration) {
Expand Down
65 changes: 38 additions & 27 deletions src/main/kotlin/me/kruase/minenopoly/MinenopolyEvents.kt
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package me.kruase.minenopoly

import org.bukkit.event.Listener
import me.kruase.minenopoly.events.chat
import me.kruase.minenopoly.util.*
import org.bukkit.Material
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
import org.bukkit.event.player.AsyncPlayerChatEvent
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.event.player.PlayerDropItemEvent
import org.bukkit.event.entity.EntityPickupItemEvent
import org.bukkit.event.Listener
import org.bukkit.event.block.BlockBreakEvent
import org.bukkit.event.block.BlockDamageEvent
import org.bukkit.event.block.BlockDropItemEvent
import org.bukkit.event.player.PlayerItemConsumeEvent
import org.bukkit.event.block.BlockPlaceEvent
import org.bukkit.entity.Player
import org.bukkit.Material
import org.bukkit.event.entity.EntityPickupItemEvent
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.event.player.AsyncPlayerChatEvent
import org.bukkit.event.player.PlayerDropItemEvent
import org.bukkit.event.player.PlayerItemConsumeEvent
import org.bukkit.inventory.ItemStack
import org.bukkit.ChatColor
import me.kruase.minenopoly.events.*
import me.kruase.minenopoly.util.*
import net.md_5.bungee.api.ChatColor as CC


class MinenopolyEvents : Listener {
Expand All @@ -25,8 +25,8 @@ class MinenopolyEvents : Listener {
try {
chat(event)
} catch (e: IllegalStateException) {
// "Unknown error" should never occur
event.player.sendMessage("${ChatColor.RED}${e.message ?: "Unknown error"}")
event.player.sendMessage("${CC.RED}${e.message ?: "Unknown error"}")
// "Unknown error" should never be output
}
}

Expand Down Expand Up @@ -66,18 +66,35 @@ class MinenopolyEvents : Listener {
event.block.chunk.persistentDataContainer.addItemName(event.itemInHand, event.block.location)
}

@EventHandler
fun onHouseDropItem(event: BlockDropItemEvent) {
if (
event.blockState.type != MSD.houseMaterial ||
!event.block.chunk.persistentDataContainer.hasItemName(event.block.location)
) return
event.items[0].itemStack.apply {
itemMeta = itemMeta!!.apply {
setDisplayName(
event.block.chunk.persistentDataContainer.getItemName(event.block.location)!! + CC.RESET
)
persistentDataContainer.addMark("house")
}
}
event.block.chunk.persistentDataContainer.removeItemName(event.block.location)
}

@EventHandler
fun onHotelDamage(event: BlockDamageEvent) {
if (
event.block.type != Material.LANTERN ||
event.block.type != MSD.hotelMaterial ||
!event.block.chunk.persistentDataContainer.hasItemName(event.block.location)
) return
event.block.type = Material.AIR
event.block.location.run {
world!!.dropItemNaturally(
this,
ItemStack(Material.LANTERN).apply { itemMeta = itemMeta!!
.apply {
ItemStack(MSD.hotelMaterial).apply {
itemMeta = itemMeta!!.apply {
setDisplayName(event.block.chunk.persistentDataContainer.getItemName(event.block.location)!!)
persistentDataContainer.addMark("hotel")
}
Expand All @@ -88,18 +105,12 @@ class MinenopolyEvents : Listener {
}

@EventHandler
fun onHouseDropItem(event: BlockDropItemEvent) {
fun onHeadDamage(event: BlockDamageEvent) {
if (
event.blockState.block.type != Material.SEA_PICKLE ||
!event.block.chunk.persistentDataContainer.hasItemName(event.block.location)
event.block.type !in listOf(Material.PLAYER_HEAD, Material.PLAYER_WALL_HEAD) || !event.player.isInGame()
) return
event.items[0].itemStack.apply { itemMeta = itemMeta!!
.apply {
setDisplayName(event.block.chunk.persistentDataContainer.getItemName(event.block.location)!!)
persistentDataContainer.addMark("house")
}
}
event.block.chunk.persistentDataContainer.removeItemName(event.block.location)

event.block.breakNaturally()
}

@EventHandler
Expand All @@ -109,7 +120,7 @@ class MinenopolyEvents : Listener {
}

@EventHandler
fun onGameItemPlace(event: BlockPlaceEvent) { // TODO: test this
fun onGameItemPlace(event: BlockPlaceEvent) {
if (event.itemInHand.itemMeta?.persistentDataContainer
?.run { hasAnyMark() && !hasMark("house") && !hasMark("hotel") } != true) return
event.isCancelled = true
Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/me/kruase/minenopoly/MinenopolyGameData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package me.kruase.minenopoly
import org.bukkit.block.Container


typealias MGD = MinenopolyGameData


data class MinenopolyGameData(val bank: Container) {
var moneyInGame: Int = 0
var chancesInGame: Int = 0
var communityChestsInGame: Int = 0
var housesInGame: Int = 0
var hotelsInGame: Int = 0

val propertiesInGame: MutableMap<String, Boolean> = MinenopolyStaticData.propertyTypes
.associateWith { false }.toMutableMap()
val propertiesInGame: MutableMap<String, Boolean> = MSD.propertyTypes.associateWith { false }.toMutableMap()
}
Loading

0 comments on commit 947c36a

Please # to comment.