Types
Why a value fits one slot and not another, the difference between a player and their name, enums and interfaces.
Every value in Denovo has a type: it is a number, or a piece of text, or a player, or a place in the world.
Every slot says which type it takes. An empty slot shows the type's name, like Player or Location, and the
editor only lets you drop in a value of that type. In script mode, a value of the wrong type is marked as an
error.
The types you meet most
| Type | What it is | Where you get one |
|---|---|---|
| number | Any number, whole or with decimals | Type it in: 3, 0.5 |
| text | Letters, words, sentences | Type it in. In script mode it goes in quotes: "Hello" |
| true/false | Yes or no | A comparison, or a block like is sneaking |
| Player | A player who is online | player from an event |
| Location | A point in a world, with x, y and z | location of a player or a block |
| Block | The block at one spot in the world | block at a location, clickedBlock from an event |
| World | A whole world, like the overworld | world of a player or a block |
| Material | A kind of block or item | A dropdown in Constants, Material.STONE in script mode |
| GameMode | Survival, creative, adventure or spectator | A dropdown in Constants, GameMode.CREATIVE in script mode |
The Types definitions list every type, where to get one, and what you can do with it.
A player is not their name
player is the player: somebody standing in your world right now. You can send them a message, teleport them,
give them items.
name of player gives you text: the letters Steve. Text is only letters. It cannot receive a message or be
teleported, because there is nobody behind it.
That is why the first slot of send the message takes a Player and nothing else. The editor will not drop
name of player into it, and in script mode event.player.getName().sendMessage("Welcome!") is refused with
"a string has no method sendMessage".
The same goes the other way round. The message slot takes text, so a Player does not belong there:
- errorArgument 1 of sendMessage needs a string, but this is a Player.
When you want to show a player's name, turn it into text on purpose with name of, and glue it into your message with join text. Join text turns numbers and other values into text for you, which is handy for things like health:
From a name back to a player
Going from a player to their name takes one block. Going back does not work: Denovo has no block that finds an online player by their name. So hold on to the Player itself for as long as you want to do something to that player, and only turn it into text at the moment you show it. Pass the Player into your functions, not the name.
Text with style
Chat messages and join messages are styled text: text that also carries colours and formatting. Styled text is its own type, so it is never like a plain piece of text, even when it reads the same:
- warningComparing a Component with a string is never equal.
plain text of strips the styling and gives you ordinary text to compare:
Enums
An enum is a type with a fixed list of named values and nothing else. GameMode is one: a game mode is
SURVIVAL, CREATIVE, ADVENTURE or SPECTATOR, and there is no fifth. Material (every block and item),
EntityType (every kind of mob and thing) and Action (every kind of click) are enums as well.
You pick enum values from the purple dropdown blocks in Constants. In script mode you write the type, a dot
and the value: GameMode.CREATIVE. The Constants definitions list every value.
The classic mistake
Say you want to stop people flying around in creative mode in your lobby. This looks right, but never does anything:
- warningComparing a GameMode with a string is never equal.
game mode of player gives you a GameMode, not text. A GameMode is never like a piece of text, not
"creative" and not "CREATIVE" either, so the condition is always false. The editor warns you about exactly
that.
Compare it with the enum value instead:
Why not compare the text?
text of turns any value into text, and the text of an enum value is its name. So this one really does work:
It is still the wrong way to do it:
- Nothing checks the text. Write
"Creative"or"CREATVE"and the condition is quietly never true. The dropdown only offers values that exist, and a comparison with a real GameMode is checked by the editor. - Text of is meant for people. It is there to show a value in chat. Its exact wording is not a promise, and for some types it has already changed between Minecraft versions (see interfaces below).
- Nobody writes it like that in Java either. In a real Minecraft plugin,
mode.toString().equals("CREATIVE")would not get through a code review. Enum values are compared directly, withmode == GameMode.CREATIVE. Text only comes in at the edges, for example when a player types a game mode into a command. There you turn the text into the enum value once, check that it was a real one, and compare the enum value from then on.
Your own enums
Make an enum under My Blocks creates an enum of your own. It works exactly like GameMode:
Interfaces
An interface describes what something can do, without saying what it is made of. Player is an interface. The Minecraft server has its own code behind every player, and scripts never see that code. They only see the promise: this thing has a name and a location, it can be sent a message, it can be teleported.
One value can keep several promises at once. A Player is also:
- an Entity: anything that exists in the world and can move, like mobs, arrows and dropped items
- a LivingEntity: an entity with health that can die
- a CommandSender: anything that can receive chat messages and run commands, including the server console
This is why the Paper javadoc lists send the message under CommandSender and location of under Entity: those blocks work on anything that keeps that promise, and a Player keeps them all. The Types definitions show what each type also counts as.
Interfaces that look like enums
Some dropdowns in Constants hold interface values rather than enum values: Sound, Biome, Attribute, Villager Profession and a few more. They used to be enums. In recent Minecraft versions they were turned into interfaces backed by the game's registries, which lets the server hold values that are not built into the game, like biomes added by a data pack. Their list of values is no longer fixed, and a value from a data pack does not have to be named like the built-in ones.
In your scripts nothing changes as long as you stick to the dropdowns: pick a value and compare with like. It is one more reason to never compare values through their text. The Constants definitions mark each type as an enum or an interface.