Denovo
Tutorial

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

TypeWhat it isWhere you get one
numberAny number, whole or with decimalsType it in: 3, 0.5
textLetters, words, sentencesType it in. In script mode it goes in quotes: "Hello"
true/falseYes or noA comparison, or a block like is sneaking
PlayerA player who is onlineplayer from an event
LocationA point in a world, with x, y and zlocation of a player or a block
BlockThe block at one spot in the worldblock at a location, clickedBlock from an event
WorldA whole world, like the overworldworld of a player or a block
MaterialA kind of block or itemA dropdown in Constants, Material.STONE in script mode
GameModeSurvival, creative, adventure or spectatorA 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:

This does not work
when a player joinsplayerjoinMessage
send player the message player
  • 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:

when a player joinsplayerjoinMessage
send player the message join text Welcome, name of player+
send player the message join text You have health of player 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:

This does not work
when a player chatsplayermessage
if message like hi
send player the message Hi yourself!
  • warningComparing a Component with a string is never equal.

plain text of strips the styling and gives you ordinary text to compare:

when a player chatsplayermessage
if plain text of message like hi
send player the message Hi yourself!

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:

This does not work
when a player joinsplayerjoinMessage
if game mode of player like creative
send player the message No flying in the lobby!
  • 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:

when a player joinsplayerjoinMessage
if game mode of player like Creative ▾
set game mode of player to Survival ▾
send player the message No flying in the lobby!

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:

This works, but avoid it
when a player joinsplayerjoinMessage
if text of game mode of player like CREATIVE
send player the message No flying in the lobby!

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, with mode == 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:

define greetpteam
if team like Team.RED ▾
send p a Red ▾ message You are on the red team.
else
send p a Blue ▾ message You are on the blue team.
when the command /red is runplayerargs
greet pplayer teamTeam.RED ▾

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.

Next up: a flint and steel that turns any block into TNT.

On this page