Skip to content

Commit

Permalink
Mineclone compatibility (#8)
Browse files Browse the repository at this point in the history
* splitting up and genericizing some code, localizing default-dependent stuff in one file

* make cooling lava an API as well

* split out spring code, start roughing in mineclone support

* ooh, at some point altitude checking was added to ABM definitions. Awesome.

* fix crash in flow through

* adding mapgen spring clay. Mineclone2 and Mineclone5 both need to accept pull requests fixing bugs before this will work
  • Loading branch information
FaceDeer authored Sep 17, 2022
1 parent cf67547 commit 7bdc95c
Show file tree
Hide file tree
Showing 10 changed files with 765 additions and 575 deletions.
133 changes: 133 additions & 0 deletions autotranslate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# A quick-and-dirty script to run untranslated text through Google Translate's API.
# The result will likely include comical errors a native speaker will laugh at you for
# or that will puzzle them, and some manual correction of escaped codes such as @1 and @= may be
# required, but hopefully it will serve as a start to something useful

# Copyright (C) 2020 FaceDeer
# LGPLv2.1+

# See https://github.com/minetest-tools/update_translations for
# potential future updates to this script.

from googletrans import Translator, LANGUAGES
import os, re, shutil

pattern_tr_filename = re.compile(r'\.tr$')
pattern_tr_id = re.compile(r'\.([^.]*)\.tr$')
pattern_line_to_translate = re.compile(r'^([^#].*[^@])=$') #finds lines that don't have a translation

translator = Translator()

def translate(tr_filename):
lang_id = pattern_tr_id.search(tr_filename)
if not lang_id:
print("Could not find language ID in tr filename " + tr_filename)
return

lang_id = lang_id.group(1)

if not lang_id in LANGUAGES:
print("language ID " + lang_id + " is not supported by Google Translate's API")
return

lines_to_translate = [] # this list of strings will ultimately be sent to Google for translation
with open(tr_filename, "r", encoding="utf-8") as tr_file_handle:
for line in tr_file_handle:
# Look for lines that end in "=", ie, that don't have a valid translation added to them
line_lacking_translation = pattern_line_to_translate.search(line)
if line_lacking_translation:
#break the line up at @n markers, this is not ideal for Google
#as it may remove some context but it's necessary to allow the
#@n markers to be preserved in the output later
lines_to_translate = lines_to_translate + line_lacking_translation.group(1).split("@n")

# Remove duplicates, and the empty string (a common artefact of splitting)
line_set = set(lines_to_translate)
line_set.discard("")
lines_to_translate = list(line_set)

# Only do more work if there are lines in need of translation
if lines_to_translate:
print("Calling Google API for " + tr_filename)
output = translator.translate(lines_to_translate, src="en", dest=lang_id)

#convert the output translations into a dictionary for easy substitution later
translation_dictionary = dict()
for out_line in output:
#Google's API sometimes seems to fail to translate a line for no apparent reason
#Don't put them in the dictionary, we can leave those untranslated and maybe try again
if out_line.origin != out_line.text:
translation_dictionary[out_line.origin] = out_line.text

translation_dictionary["@n"] = "@n" #These are to be left unchanged

tr_file_handle.seek(0)
with open(tr_filename + ".temp", "w", encoding="utf-8") as tr_file_new:
for line in tr_file_handle:
line_lacking_translation = pattern_line_to_translate.search(line)
if line_lacking_translation:
line = line.rstrip('\n') #remove trailing newline so we can add the translated string to the same line
line_split = re.split("(@n)", line[:-1]) #slice to leave off the "=" that's the last character of the line
translated_line = ""

#After splitting the line up on @n again, as was done before, we should have
#line segments that match the strings that were sent to Google.
for line_piece in line_split:
if line_piece in translation_dictionary:
translated_line = translated_line + translation_dictionary[line_piece]
else:
print("Google returned string unchanged in file " + tr_filename + ":")
print(line_piece)
translated_line = None
break

if translated_line:
tr_file_new.write("#WARNING: AUTOTRANSLATED BY GOOGLE TRANSLATE\n")
tr_file_new.write(line)
tr_file_new.write(translated_line)
tr_file_new.write("\n")
else:
tr_file_new.write(line)
tr_file_new.write("\n")
else:
tr_file_new.write(line)
shutil.move(tr_filename + ".temp", tr_filename) # Overwrite the original file with the new one

pattern_domain = re.compile(r'^# textdomain: (.+)$')

def create_tr_files_from_template(folder, lang_id):
if not lang_id in LANGUAGES:
print("language ID " + lang_id + " is not supported by Google Translate's API")
return
for root, dirs, files in os.walk(folder):
if root == "." or os.path.split(root)[1] == "locale":
for name in files:
if name == "template.txt":
template_filename = os.path.join(root,name)
with open(template_filename, "r", encoding="utf-8") as template_file:
first_line = template_file.readline()
domain = pattern_domain.search(first_line)
if domain:
translation_filename = domain.group(1) + "." + lang_id + ".tr"
translation_filename = os.path.join(root,translation_filename)
if not os.path.isfile(translation_filename):
print("Copying template.txt to " + translation_filename)
shutil.copy(template_filename, translation_filename)
else:
print(translation_filename + " already exists")

#If there are already .tr files in /locale, returns a list of their names
def get_existing_tr_files(folder):
out = []
for root, dirs, files in os.walk(folder):
for name in files:
if pattern_tr_filename.search(name):
out.append(os.path.join(root,name))
return out

#create_tr_files_from_template(".", "de")
#create_tr_files_from_template(".", "it")

tr_files = get_existing_tr_files(".")
for tr_file in tr_files:
translate(tr_file)
59 changes: 30 additions & 29 deletions cooling_lava.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
if not minetest.get_modpath("default") then return end
dynamic_liquid.cooling_lava = function(def)

local new_lava_cooling = minetest.settings:get_bool("dynamic_liquid_new_lava_cooling", true)
if not new_lava_cooling then return end
local lava_source = def.lava_source
local lava_flowing = def.lava_flowing
local obsidian = def.obsidian
local flowing_destroys = def.flowing_destroys or {}
local source_destroys = def.source_destroys or {}
local cooling_sound = def.cooling_sound

local falling_obsidian = dynamic_liquid.config.falling_obsidian

local falling_obsidian = minetest.settings:get_bool("dynamic_liquid_falling_obsidian", false)

-- The existing cool_lava ABM is hard-coded to respond to water nodes
-- and overriding node groups doesn't appear to work:
Expand All @@ -20,7 +25,6 @@ local falling_obsidian = minetest.settings:get_bool("dynamic_liquid_falling_obsi
-- to nodes that should be destroyed by proximity to lava.

local particles = minetest.settings:get_bool("enable_particles", true)

local steam = function(pos)
if particles then
minetest.add_particlespawner({
Expand All @@ -43,22 +47,19 @@ local steam = function(pos)
end
end

default.cool_lava = function(pos, node)
-- no-op disables default cooling ABM
end

-------------------------------------------------------------------------------------------------


local dynamic_cools_lava_flowing = {"group:dynamic_cools_lava_flowing", "group:cools_lava"}

-- Flowing lava will turn these blocks into steam.
local dynamic_lava_flowing_destroys = {
"group:dynamic_lava_flowing_destroys",
"default:water_flowing",
"default:river_water_flowing",
"default:snow",
"default:snowblock"
}
for _, node_name in pairs(flowing_destroys) do
table.insert(dynamic_lava_flowing_destroys, node_name)
end

local all_flowing_nodes = {unpack(dynamic_cools_lava_flowing)}
for i = 1, #dynamic_lava_flowing_destroys do
Expand All @@ -71,9 +72,9 @@ local cool_lava_flowing = function(pos, node)
if cooler_adjacent ~= nil then
-- pulling nearby sources into position is necessary to break certain classes of
-- flow "deadlock". Weird, but what're you gonna do.
local nearby_source = minetest.find_node_near(pos, 1, "default:lava_source")
local nearby_source = minetest.find_node_near(pos, 1, lava_source)
if nearby_source then
minetest.set_node(pos, {name="default:lava_source"})
minetest.set_node(pos, {name=lava_source})
minetest.set_node(nearby_source, {name="air"})
steam(nearby_source)
else
Expand All @@ -92,13 +93,13 @@ local cool_lava_flowing = function(pos, node)
steam(loc)
end

minetest.sound_play("default_cool_lava",
minetest.sound_play(cooling_sound,
{pos = pos, max_hear_distance = 16, gain = 0.25})
end

minetest.register_abm({
label = "Lava flowing cooling",
nodenames = {"default:lava_flowing"},
nodenames = {lava_flowing},
neighbors = all_flowing_nodes,
interval = 1,
chance = 1,
Expand All @@ -122,14 +123,11 @@ end
-- lava source blocks will turn these blocks into steam.
local dynamic_lava_source_destroys = {
"group:dynamic_lava_source_destroys",
"default:water_source",
"default:river_water_source",
"default:water_flowing",
"default:river_water_flowing",
"default:ice",
"default:snow",
"default:snowblock"
}
for _, node_name in pairs(source_destroys) do
table.insert(dynamic_lava_source_destroys, node_name)
end


local all_source_nodes = {unpack(dynamic_cools_lava_source)}
for i = 1, #dynamic_lava_source_destroys do
Expand Down Expand Up @@ -193,32 +191,35 @@ local cool_lava_source = function(pos, node)

if obsidian_location ~= nil then
minetest.set_node(pos, {name = "air"})
minetest.set_node(obsidian_location, {name = "default:obsidian"})
if minetest.spawn_falling_node and falling_obsidian then -- TODO cutting-edge dev function, so check if it exists for the time being. Remove check when 0.4.16 is released.
minetest.set_node(obsidian_location, {name = obsidian})
if falling_obsidian then
minetest.spawn_falling_node(obsidian_location)
end
elseif #evaporate_list > 0 then
-- Again, this weird bit is necessary for breaking certain types of flow deadlock
local loc = evaporate_list[math.random(1,#evaporate_list)]
if loc.y <= pos.y then
minetest.set_node(pos, {name = "air"})
minetest.set_node(loc, {name = "default:lava_source"})
minetest.set_node(loc, {name = lava_source})
end
end

minetest.sound_play("default_cool_lava",
minetest.sound_play(cooling_sound,
{pos = pos, max_hear_distance = 16, gain = 0.25})
end


minetest.register_abm({
label = "Lava source cooling",
nodenames = {"default:lava_source"},
nodenames = {lava_source},
neighbors = all_source_nodes,
interval = 1,
chance = 1,
catch_up = false,
action = function(...)
cool_lava_source(...)
end,
})
})


end
Loading

0 comments on commit 7bdc95c

Please sign in to comment.