Skip to content

Commit

Permalink
feat: Chat configuration
Browse files Browse the repository at this point in the history
Configuration is now generated with a beet plugin. This allows for configuration via chat and book
  • Loading branch information
OrangeUtan committed Jul 6, 2021
1 parent 9667af1 commit 2612506
Show file tree
Hide file tree
Showing 18 changed files with 348 additions and 89 deletions.
2 changes: 2 additions & 0 deletions beet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pipeline:
- beet.contrib.installation_advancement
- babelbox.integration.beet
- mcanitexgen.integration.beet
- hats.plugins.configuration
- hats.plugins.hat_loot_tables
- hats.plugins.item_models
- hats.plugins.hat_recipes
Expand All @@ -35,6 +36,7 @@ meta:
render:
data_pack:
advancements: ["oran9eutan:*"]
functions: ["oran9eutan:*"]
installation_advancement:
author_skull_owner: Oran9eUtan
icon:
Expand Down
1 change: 0 additions & 1 deletion datapack/data/oran9eutan/functions/hats/cfg.mcfunction

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# executor: Player getting advancement

# Convert all nearby dog hat items into dogs
execute if score #opt_convert_dogs hats.cfg matches 1 as @e[type=item,distance=..2,nbt={Item:{tag:{Tags:["hats.hat.type.dog"]}}}] at @s if data entity @s Item.tag.dog_data run function oran9eutan:hats/dog_mechanism/copy_dog_data_from_item
execute if {{ hats.setting["dog_conversion"].is_true }} as @e[type=item,distance=..2,nbt={Item:{tag:{Tags:["hats.hat.type.dog"]}}}] at @s if data entity @s Item.tag.dog_data run function oran9eutan:hats/dog_mechanism/copy_dog_data_from_item

# Reset trigger
scoreboard players set @s hats.dropLthrHlm 0
scoreboard players set @s hats.dropStick 0
advancement revoke @s only oran9eutan:hats/event/player_dropped_hat_item
advancement revoke @s only oran9eutan:hats/event/player_dropped_hat_item
14 changes: 2 additions & 12 deletions datapack/data/oran9eutan/functions/hats/install.mcfunction
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,8 @@ scoreboard objectives add hats.dropLthrHlm minecraft.dropped:minecraft.leather_h
scoreboard objectives add hats.dropStick minecraft.dropped:minecraft.stick
scoreboard objectives add hats.fix_old_hat trigger

#region: Init settings

#define score_holder #opt_convert_dogs Should Players be able to convert dogs to hats and back
execute unless score #opt_convert_dogs hats.cfg matches -2147483648.. run scoreboard players set #opt_convert_dogs hats.cfg 1

#define score_holder #opt_dress_mobs Randomly dress mobs in the world with hats
execute unless score #opt_dress_mobs hats.cfg matches -2147483648.. run scoreboard players set #opt_dress_mobs hats.cfg 1

#define score_holder #opt_enable_fix_old_hats Should players be able to fix their old hats
execute unless score #opt_enable_fix_old_hats hats.cfg matches -2147483648.. run scoreboard players set #opt_enable_fix_old_hats hats.cfg 0

#endregion
# Initialize settings
function oran9eutan:hats/cfg/init

# Flag datapack as installed
data modify storage oran9eutan.hats version set value {"major": 2, "minor": 3, "patch": 1}
5 changes: 2 additions & 3 deletions datapack/data/oran9eutan/functions/hats/load.mcfunction
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ scoreboard objectives add hats.cfg dummy
execute unless data storage minecraft:oran9eutan.hats {"version":{"major": 2, "minor": 3, "patch": 1}} run function oran9eutan:hats/install

#Start looping functions
execute if score #opt_convert_dogs hats.cfg matches 1 run function oran9eutan:hats/loops/convert_dogs_near_players
execute if score #opt_dress_mobs hats.cfg matches 1 run function oran9eutan:hats/loops/dress_mobs
execute if score #opt_enable_fix_old_hats hats.cfg matches 1 run function oran9eutan:hats/loops/did_player_triggered_fix_old_hat
execute if {{ hats.setting["dog_conversion"].is_true }} run function oran9eutan:hats/loops/convert_dogs_near_players
execute if {{ hats.setting["dress_mobs"].is_true }} run function oran9eutan:hats/loops/dress_mobs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
execute as @a[tag=!global.ignore] at @s if predicate oran9eutan:hats/player/can_convert_dogs if entity @e[tag=!global.ignore,type=minecraft:wolf,distance=..2,predicate=oran9eutan:hats/entity/is_sitting] run function oran9eutan:hats/dog_mechanism/convert_owned_dogs_nearby

# Loop if enabled
execute if score #opt_convert_dogs hats.cfg matches 1 run schedule function oran9eutan:hats/loops/convert_dogs_near_players 1s
execute if {{ hats.setting["dog_conversion"].is_true }} run schedule function oran9eutan:hats/loops/convert_dogs_near_players 1s

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
execute as @a[tag=!global.ignore] at @s positioned ^ ^ ^25 run function oran9eutan:hats/dress/dress_mobs_near_player

# loop
execute if score #opt_dress_mobs hats.cfg matches 1 run schedule function oran9eutan:hats/loops/dress_mobs 5s
execute if {{ hats.setting["dress_mobs"].is_true }} run schedule function oran9eutan:hats/loops/dress_mobs 5s
23 changes: 0 additions & 23 deletions datapack/data/oran9eutan/loot_tables/hats/cfg.json

This file was deleted.

219 changes: 219 additions & 0 deletions hats/plugins/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import json
from logging import getLogger
from typing import Any, Optional

from beet import Context
from beet.library.data_pack import DataPack, Function, LootTable

from hats.registry.settings import Section, Setting, SettingsRegistry, SettingType

logger = getLogger(__name__)


def beet_default(ctx: Context):
namespace = ctx.meta["namespace"]
config = ctx.meta["hats"]
registry = SettingsRegistry.get()

config["setting"] = {
s.id: {
"is_true": f"score {s.scoreboard_holder} {registry.scoreboard} matches 1",
"is_false": f"score {s.scoreboard_holder} {registry.scoreboard} matches 0",
}
for s in registry.settings.values()
}

create_chat_config(ctx, registry, namespace)
ctx.data.loot_tables[f"{namespace}/cfg"] = create_config_book_loot_table(
ctx, registry, namespace
)
ctx.data.functions[f"{namespace}/cfg_book"] = Function(
["loot give @s loot oran9eutan:hats/cfg"]
)


def create_chat_config(ctx: Context, registry: SettingsRegistry, namespace: str):
ctx.data.functions[f"{namespace}/cfg/init"] = create_init_settings_function(registry)

for section in registry.sections.values():
ctx.data.merge(create_section(section, registry, ctx.project_name, namespace))

ctx.data.functions[f"{namespace}/cfg"] = Function(
[f"function {registry.main_function(namespace)}", cmd_blank_line]
)


def create_config_book_loot_table(ctx: Context, registry: SettingsRegistry, namespace: str):
CHECK = "\u2714"
CROSS = "\u00D7"
LOOP = "\u27f2"

pages = []
for section in registry.sections.values():
# Section header
page = [f"{section.title}:\n"]

# Interactive settings
for setting in section.settings.values():
if setting.type == SettingType.BOOL:
enable_function = f"{section.section_root(namespace)}/enable_{setting.id}"
disable_function = f"{section.section_root(namespace)}/disable_{setting.id}"
reset_function = enable_function if setting.default else disable_function

page += [
"- ",
textcomp_interactive(setting.title, hover_text=setting.description),
": ",
textcomp_interactive(CHECK, "dark_green", "Enable", enable_function),
textcomp_interactive(CROSS, "red", "Disable", disable_function),
textcomp_interactive(f"{LOOP}\n", "aqua", "Reset", reset_function),
]

pages.append(json.dumps(page))

return LootTable(
{
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:written_book",
"functions": [
{
"function": "minecraft:set_nbt",
"tag": f'{{title: "{ctx.project_name} Configuration", author: "{ctx.project_author}"}}',
},
{"function": "minecraft:set_nbt", "tag": f"{{pages:{pages}}}"},
],
}
],
}
]
}
)


def textcomp_interactive(
text: str,
color: Optional[str] = None,
hover_text: Optional[str] = None,
on_click: Optional[str] = None,
):
textcomp = {"text": text}

if color:
textcomp["color"] = color
if hover_text:
textcomp["hoverEvent"] = {"action": "show_text", "contents": hover_text}
if on_click:
textcomp["clickEvent"] = {"action": "run_command", "value": f"/function {on_click}"}

return textcomp


def create_init_settings_function(registry: SettingsRegistry):
lines = []
for setting in registry.settings.values():
if setting.type == SettingType.BOOL:
lines.append(
f"execute unless score {setting.scoreboard_holder} {registry.scoreboard} matches -2147483648.. run {cmd_set_score(setting.scoreboard_holder, registry.scoreboard, 1 if setting.default else 0)}"
)

return Function(lines)


def create_section(section: Section, registry: SettingsRegistry, project_name: str, namespace: str):
data = DataPack()

section_root = section.section_root(namespace)
project_title = f"{project_name} config: "

# Show header
lines = [
f'tellraw @s ["",{{"text":"{project_title}","color":"gold"}}, {{"text": "{section.title}"}}]',
f"tellraw @s {{\"text\":\"{'-'*len(project_title)}\"}}",
]

# List settings
for setting in section.settings.values():
lines += cmds_show_setting_config(setting, registry, section_root)
data.functions[f"{section_root}/enable_{setting.id}"] = create_set_bool_setting_function(
setting, registry.scoreboard, True, section_root
)
data.functions[f"{section_root}/disable_{setting.id}"] = create_set_bool_setting_function(
setting, registry.scoreboard, False, section_root
)

# Fill chat window
lines += [cmd_blank_line for _ in range(section.MAX_LINES - len(lines) + 2)]

data.functions[section.main_function(namespace)] = Function(lines)
return data


def create_set_bool_setting_function(
setting: Setting, scoreboard: str, value: bool, section_root: str
):
lines = [
cmd_set_score(setting.scoreboard_holder, scoreboard, 1 if value else 0),
f"function {section_root}/main",
]

if value and setting.on_enable:
lines.append(setting.on_enable)
elif not value and setting.on_disable:
lines.append(setting.on_disable)

return Function(lines)


def textcomp_set_bool_setting(setting: Setting, value: bool, change_function: str):
textcomp = {
"text": setting.title,
"clickEvent": {"action": "run_command", "value": f"/function {change_function}"},
"hoverEvent": {"action": "show_text", "contents": setting.description},
}

if value:
textcomp["strikethrough"] = True
textcomp["color"] = "gray"

return textcomp


def cmd_set_score(scoreboard_holder: str, scoreboard: str, value: int):
return f"scoreboard players set {scoreboard_holder} {scoreboard} {value}"


def cmd_if_score(scoreboard_holder: str, scoreboard: str, value: int, then: Any):
return f"execute as @s if score {scoreboard_holder} {scoreboard} matches {value} run {then}"


def cmds_show_setting_config(setting: Setting, registry: SettingsRegistry, section_root: str):
if setting.type == SettingType.BOOL:
textcomp_enable = textcomp_set_bool_setting(
setting, True, f"{section_root}/enable_{setting.id}"
)
textcomp_disable = textcomp_set_bool_setting(
setting, False, f"{section_root}/disable_{setting.id}"
)

return [
cmd_if_score(
setting.scoreboard_holder,
registry.scoreboard,
0,
f'tellraw @s [{{"text": "- "}}, {json.dumps(textcomp_enable)}]',
),
cmd_if_score(
setting.scoreboard_holder,
registry.scoreboard,
1,
f'tellraw @s [{{"text": "- "}}, {json.dumps(textcomp_disable)}]',
),
]


cmd_blank_line = f'tellraw @s [""]'
Loading

0 comments on commit 2612506

Please sign in to comment.