Mass replace package types

This commit is contained in:
Armen 2022-02-15 21:04:19 -05:00
parent e4dcb89d2e
commit 311bfd2199
48 changed files with 264 additions and 264 deletions

View File

@ -89,7 +89,7 @@ def resolve_package_deps(out, package, only_hard, depth=1):
ret = [] ret = []
out[id] = ret out[id] = ret
if package.type != PackageType.MOD: if package.type != PackageType.TOOL:
return return
for dep in package.dependencies: for dep in package.dependencies:
@ -106,7 +106,7 @@ def resolve_package_deps(out, package, only_hard, depth=1):
fulfilled_by = [ pkg.getId() for pkg in dep.meta_package.packages] fulfilled_by = [ pkg.getId() for pkg in dep.meta_package.packages]
if depth == 1 and not dep.optional: if depth == 1 and not dep.optional:
most_likely = next((pkg for pkg in dep.meta_package.packages if pkg.type == PackageType.MOD), None) most_likely = next((pkg for pkg in dep.meta_package.packages if pkg.type == PackageType.TOOL), None)
if most_likely: if most_likely:
resolve_package_deps(out, most_likely, only_hard, depth + 1) resolve_package_deps(out, most_likely, only_hard, depth + 1)
@ -470,9 +470,9 @@ def homepage():
featured = query.filter(Package.tags.any(name="featured")).order_by( featured = query.filter(Package.tags.any(name="featured")).order_by(
func.random()).limit(6).all() func.random()).limit(6).all()
new = query.order_by(db.desc(Package.approved_at)).limit(4).all() new = query.order_by(db.desc(Package.approved_at)).limit(4).all()
pop_mod = query.filter_by(type=PackageType.MOD).order_by(db.desc(Package.score)).limit(8).all() pop_mod = query.filter_by(type=PackageType.TOOL).order_by(db.desc(Package.score)).limit(8).all()
pop_gam = query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score)).limit(8).all() pop_gam = query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score)).limit(8).all()
pop_txp = query.filter_by(type=PackageType.TXP).order_by(db.desc(Package.score)).limit(8).all() pop_txp = query.filter_by(type=PackageType.ASSETPACK).order_by(db.desc(Package.score)).limit(8).all()
high_reviewed = query.order_by(db.desc(Package.score - Package.score_downloads)) \ high_reviewed = query.order_by(db.desc(Package.score - Package.score_downloads)) \
.filter(Package.reviews.any()).limit(4).all() .filter(Package.reviews.any()).limit(4).all()

View File

@ -20,9 +20,9 @@ def home():
featured = query.filter(Package.tags.any(name="featured")).order_by(func.random()).limit(6).all() featured = query.filter(Package.tags.any(name="featured")).order_by(func.random()).limit(6).all()
new = join(query.order_by(db.desc(Package.approved_at))).limit(4).all() new = join(query.order_by(db.desc(Package.approved_at))).limit(4).all()
pop_mod = join(query.filter_by(type=PackageType.MOD).order_by(db.desc(Package.score))).limit(8).all() pop_mod = join(query.filter_by(type=PackageType.TOOL).order_by(db.desc(Package.score))).limit(8).all()
pop_gam = join(query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score))).limit(8).all() pop_gam = join(query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score))).limit(8).all()
pop_txp = join(query.filter_by(type=PackageType.TXP).order_by(db.desc(Package.score))).limit(8).all() pop_txp = join(query.filter_by(type=PackageType.ASSETPACK).order_by(db.desc(Package.score))).limit(8).all()
high_reviewed = join(query.order_by(db.desc(Package.score - Package.score_downloads))) \ high_reviewed = join(query.order_by(db.desc(Package.score - Package.score_downloads))) \
.filter(Package.reviews.any()).limit(4).all() .filter(Package.reviews.any()).limit(4).all()

View File

@ -37,9 +37,9 @@ def game_hub(package: Package):
count = query.count() count = query.count()
new = join(query.order_by(db.desc(Package.approved_at))).limit(4).all() new = join(query.order_by(db.desc(Package.approved_at))).limit(4).all()
pop_mod = join(query.filter_by(type=PackageType.MOD).order_by(db.desc(Package.score))).limit(8).all() pop_mod = join(query.filter_by(type=PackageType.TOOL).order_by(db.desc(Package.score))).limit(8).all()
pop_gam = join(query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score))).limit(8).all() pop_gam = join(query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score))).limit(8).all()
pop_txp = join(query.filter_by(type=PackageType.TXP).order_by(db.desc(Package.score))).limit(8).all() pop_txp = join(query.filter_by(type=PackageType.ASSETPACK).order_by(db.desc(Package.score))).limit(8).all()
high_reviewed = join(query.order_by(db.desc(Package.score - Package.score_downloads))) \ high_reviewed = join(query.order_by(db.desc(Package.score - Package.score_downloads))) \
.filter(Package.reviews.any()).limit(4).all() .filter(Package.reviews.any()).limit(4).all()

View File

@ -120,7 +120,7 @@ def view(package):
package.checkPerm(current_user, Permission.APPROVE_NEW)) package.checkPerm(current_user, Permission.APPROVE_NEW))
conflicting_modnames = None conflicting_modnames = None
if show_similar and package.type != PackageType.TXP: if show_similar and package.type != PackageType.ASSETPACK:
conflicting_modnames = db.session.query(MetaPackage.name) \ conflicting_modnames = db.session.query(MetaPackage.name) \
.filter(MetaPackage.id.in_([ mp.id for mp in package.provides ])) \ .filter(MetaPackage.id.in_([ mp.id for mp in package.provides ])) \
.filter(MetaPackage.packages.any(Package.id != package.id)) \ .filter(MetaPackage.packages.any(Package.id != package.id)) \
@ -136,9 +136,9 @@ def view(package):
conflicting_modnames = set([x[0] for x in conflicting_modnames]) conflicting_modnames = set([x[0] for x in conflicting_modnames])
packages_uses = None packages_uses = None
if package.type == PackageType.MOD: if package.type == PackageType.TOOL:
packages_uses = Package.query.filter( packages_uses = Package.query.filter(
Package.type == PackageType.MOD, Package.type == PackageType.TOOL,
Package.id != package.id, Package.id != package.id,
Package.state == PackageState.APPROVED, Package.state == PackageState.APPROVED,
Package.dependencies.any( Package.dependencies.any(
@ -164,7 +164,7 @@ def view(package):
if topic.author != package.author: if topic.author != package.author:
errors.append("<b>" + gettext("Error: Forum topic author doesn't match package author.") + "</b>") errors.append("<b>" + gettext("Error: Forum topic author doesn't match package author.") + "</b>")
topic_error_lvl = "danger" topic_error_lvl = "danger"
elif package.type != PackageType.TXP: elif package.type != PackageType.ASSETPACK:
errors.append(gettext("Warning: Forum topic not found. This may happen if the topic has only just been created.")) errors.append(gettext("Warning: Forum topic not found. This may happen if the topic has only just been created."))
topic_error = "<br />".join(errors) topic_error = "<br />".join(errors)
@ -226,7 +226,7 @@ def makeLabel(obj):
class PackageForm(FlaskForm): class PackageForm(FlaskForm):
type = SelectField(lazy_gettext("Type"), [InputRequired()], choices=PackageType.choices(), coerce=PackageType.coerce, default=PackageType.MOD) type = SelectField(lazy_gettext("Type"), [InputRequired()], choices=PackageType.choices(), coerce=PackageType.coerce, default=PackageType.TOOL)
title = StringField(lazy_gettext("Title (Human-readable)"), [InputRequired(), Length(1, 100)]) title = StringField(lazy_gettext("Title (Human-readable)"), [InputRequired(), Length(1, 100)])
name = StringField(lazy_gettext("Name (Technical)"), [InputRequired(), Length(1, 100), Regexp("^[a-z0-9_]+$", 0, lazy_gettext("Lower case letters (a-z), digits (0-9), and underscores (_) only"))]) name = StringField(lazy_gettext("Name (Technical)"), [InputRequired(), Length(1, 100), Regexp("^[a-z0-9_]+$", 0, lazy_gettext("Lower case letters (a-z), digits (0-9), and underscores (_) only"))])
short_desc = StringField(lazy_gettext("Short Description (Plaintext)"), [InputRequired(), Length(1,200)]) short_desc = StringField(lazy_gettext("Short Description (Plaintext)"), [InputRequired(), Length(1,200)])
@ -293,7 +293,7 @@ def create_edit(author=None, name=None):
form.tags.data = package.tags form.tags.data = package.tags
form.content_warnings.data = package.content_warnings form.content_warnings.data = package.content_warnings
if request.method == "POST" and form.type.data == PackageType.TXP: if request.method == "POST" and form.type.data == PackageType.ASSETPACK:
form.license.data = form.media_license.data form.license.data = form.media_license.data
if form.validate_on_submit(): if form.validate_on_submit():

View File

@ -152,7 +152,7 @@ def get_user_medals(user: User) -> Tuple[List[Medal], List[Medal]]:
.all() .all()
user_package_ranks = next( user_package_ranks = next(
(x for x in user_package_ranks if x[0] == PackageType.MOD or x[2] <= 10), (x for x in user_package_ranks if x[0] == PackageType.TOOL or x[2] <= 10),
None) None)
if user_package_ranks: if user_package_ranks:
top_rank = user_package_ranks[2] top_rank = user_package_ranks[2]
@ -161,7 +161,7 @@ def get_user_medals(user: User) -> Tuple[List[Medal], List[Medal]]:
title = gettext(u"Top %(type)s", type=top_type.text.lower()) title = gettext(u"Top %(type)s", type=top_type.text.lower())
else: else:
title = gettext(u"Top %(group)d %(type)s", group=top_rank, type=top_type.text.lower()) title = gettext(u"Top %(group)d %(type)s", group=top_rank, type=top_type.text.lower())
if top_type == PackageType.MOD: if top_type == PackageType.TOOL:
icon = "fa-box" icon = "fa-box"
elif top_type == PackageType.GAME: elif top_type == PackageType.GAME:
icon = "fa-gamepad" icon = "fa-gamepad"

View File

@ -69,25 +69,25 @@ def populate_test_data(session):
session.add(jeija) session.add(jeija)
mod = Package() tool = Package()
mod.state = PackageState.APPROVED tool.state = PackageState.APPROVED
mod.name = "alpha" tool.name = "alpha"
mod.title = "Alpha Test" tool.title = "Alpha Test"
mod.license = licenses["MIT"] tool.license = licenses["MIT"]
mod.media_license = licenses["MIT"] tool.media_license = licenses["MIT"]
mod.type = PackageType.MOD tool.type = PackageType.TOOL
mod.author = admin_user tool.author = admin_user
mod.tags.append(tags["mapgen"]) tool.tags.append(tags["mapgen"])
mod.tags.append(tags["environment"]) tool.tags.append(tags["environment"])
mod.repo = "https://github.com/ezhh/other_worlds" tool.repo = "https://github.com/ezhh/other_worlds"
mod.issueTracker = "https://github.com/ezhh/other_worlds/issues" tool.issueTracker = "https://github.com/ezhh/other_worlds/issues"
mod.forums = 16015 tool.forums = 16015
mod.short_desc = "The content library should not be used yet as it is still in alpha" tool.short_desc = "The content library should not be used yet as it is still in alpha"
mod.desc = "This is the long desc" tool.desc = "This is the long desc"
session.add(mod) session.add(tool)
rel = PackageRelease() rel = PackageRelease()
rel.package = mod rel.package = tool
rel.title = "v1.0.0" rel.title = "v1.0.0"
rel.url = "https://github.com/ezhh/handholds/archive/master.zip" rel.url = "https://github.com/ezhh/handholds/archive/master.zip"
rel.approved = True rel.approved = True
@ -99,7 +99,7 @@ def populate_test_data(session):
mod1.title = "Awards" mod1.title = "Awards"
mod1.license = licenses["LGPLv2.1"] mod1.license = licenses["LGPLv2.1"]
mod1.media_license = licenses["MIT"] mod1.media_license = licenses["MIT"]
mod1.type = PackageType.MOD mod1.type = PackageType.TOOL
mod1.author = admin_user mod1.author = admin_user
mod1.tags.append(tags["player_effects"]) mod1.tags.append(tags["player_effects"])
mod1.repo = "https://github.com/rubenwardy/awards" mod1.repo = "https://github.com/rubenwardy/awards"
@ -135,7 +135,7 @@ awards.register_achievement("award_mesefind",{
mod2.name = "mesecons" mod2.name = "mesecons"
mod2.title = "Mesecons" mod2.title = "Mesecons"
mod2.tags.append(tags["tools"]) mod2.tags.append(tags["tools"])
mod2.type = PackageType.MOD mod2.type = PackageType.TOOL
mod2.license = licenses["LGPLv3"] mod2.license = licenses["LGPLv3"]
mod2.media_license = licenses["MIT"] mod2.media_license = licenses["MIT"]
mod2.author = jeija mod2.author = jeija
@ -150,7 +150,7 @@ Mezzee-what?
------------ ------------
[Mesecons](http://mesecons.net/)! They're yellow, they're conductive, and they'll add a whole new dimension to Minetest's gameplay. [Mesecons](http://mesecons.net/)! They're yellow, they're conductive, and they'll add a whole new dimension to Minetest's gameplay.
Mesecons is a mod for [Minetest](http://minetest.net/) that implements a ton of items related to digital circuitry, such as wires, buttons, lights, and even programmable controllers. Among other things, there are also pistons, solar panels, pressure plates, and note blocks. Mesecons is a tool for [Minetest](http://minetest.net/) that implements a ton of items related to digital circuitry, such as wires, buttons, lights, and even programmable controllers. Among other things, there are also pistons, solar panels, pressure plates, and note blocks.
Mesecons has a similar goal to Redstone in Minecraft, but works in its own way, with different rules and mechanics. Mesecons has a similar goal to Redstone in Minecraft, but works in its own way, with different rules and mechanics.
@ -160,14 +160,14 @@ Go get it!
[DOWNLOAD IT NOW](https://github.com/minetest-mods/mesecons/archive/master.zip) [DOWNLOAD IT NOW](https://github.com/minetest-mods/mesecons/archive/master.zip)
Now go ahead and install it like any other Minetest mod. Don't know how? Check out [the wonderful page about it](http://wiki.minetest.com/wiki/Mods) over at the Minetest Wiki. For your convenience, here's a quick summary: Now go ahead and install it like any other Minetest tool. Don't know how? Check out [the wonderful page about it](http://wiki.minetest.com/wiki/Mods) over at the Minetest Wiki. For your convenience, here's a quick summary:
1. If Mesecons is still in a ZIP file, extract the folder inside to somewhere on the computer. 1. If Mesecons is still in a ZIP file, extract the folder inside to somewhere on the computer.
2. Make sure that when you open the folder, you can directly find `README.md` in the listing. If you just see another folder, move that folder up one level and delete the old one. 2. Make sure that when you open the folder, you can directly find `README.md` in the listing. If you just see another folder, move that folder up one level and delete the old one.
3. Open up the Minetest mods folder - usually `/mods/`. If you see the `minetest` or folder inside of that, that is your mod folder instead. 3. Open up the Minetest mods folder - usually `/mods/`. If you see the `minetest` or folder inside of that, that is your tool folder instead.
4. Copy the Mesecons folder into the mods folder. 4. Copy the Mesecons folder into the mods folder.
Don't like some parts of Mesecons? Open up the Mesecons folder and delete the subfolder containing the mod you don't want. If you didn't want movestones, for example, all you have to do is delete the `mesecons_movestones` folder and they will no longer be available. Don't like some parts of Mesecons? Open up the Mesecons folder and delete the subfolder containing the tool you don't want. If you didn't want movestones, for example, all you have to do is delete the `mesecons_movestones` folder and they will no longer be available.
There are no dependencies - it will work right after installing! There are no dependencies - it will work right after installing!
@ -219,79 +219,79 @@ No warranty is provided, express or implied, for any part of the project.
session.add(mod1) session.add(mod1)
session.add(mod2) session.add(mod2)
mod = Package() tool = Package()
mod.state = PackageState.APPROVED tool.state = PackageState.APPROVED
mod.name = "handholds" tool.name = "handholds"
mod.title = "Handholds" tool.title = "Handholds"
mod.license = licenses["MIT"] tool.license = licenses["MIT"]
mod.media_license = licenses["MIT"] tool.media_license = licenses["MIT"]
mod.type = PackageType.MOD tool.type = PackageType.TOOL
mod.author = ez tool.author = ez
mod.tags.append(tags["player_effects"]) tool.tags.append(tags["player_effects"])
mod.repo = "https://github.com/ezhh/handholds" tool.repo = "https://github.com/ezhh/handholds"
mod.issueTracker = "https://github.com/ezhh/handholds/issues" tool.issueTracker = "https://github.com/ezhh/handholds/issues"
mod.forums = 17069 tool.forums = 17069
mod.short_desc = "Adds hand holds and climbing thingies" tool.short_desc = "Adds hand holds and climbing thingies"
mod.desc = "This is the long desc" tool.desc = "This is the long desc"
session.add(mod) session.add(tool)
rel = PackageRelease() rel = PackageRelease()
rel.package = mod rel.package = tool
rel.title = "v1.0.0" rel.title = "v1.0.0"
rel.max_rel = v4 rel.max_rel = v4
rel.url = "https://github.com/ezhh/handholds/archive/master.zip" rel.url = "https://github.com/ezhh/handholds/archive/master.zip"
rel.approved = True rel.approved = True
session.add(rel) session.add(rel)
mod = Package() tool = Package()
mod.state = PackageState.APPROVED tool.state = PackageState.APPROVED
mod.name = "other_worlds" tool.name = "other_worlds"
mod.title = "Other Worlds" tool.title = "Other Worlds"
mod.license = licenses["MIT"] tool.license = licenses["MIT"]
mod.media_license = licenses["MIT"] tool.media_license = licenses["MIT"]
mod.type = PackageType.MOD tool.type = PackageType.TOOL
mod.author = ez tool.author = ez
mod.tags.append(tags["mapgen"]) tool.tags.append(tags["mapgen"])
mod.tags.append(tags["environment"]) tool.tags.append(tags["environment"])
mod.repo = "https://github.com/ezhh/other_worlds" tool.repo = "https://github.com/ezhh/other_worlds"
mod.issueTracker = "https://github.com/ezhh/other_worlds/issues" tool.issueTracker = "https://github.com/ezhh/other_worlds/issues"
mod.forums = 16015 tool.forums = 16015
mod.short_desc = "Adds space with asteroids and comets" tool.short_desc = "Adds space with asteroids and comets"
mod.desc = "This is the long desc" tool.desc = "This is the long desc"
session.add(mod) session.add(tool)
mod = Package() tool = Package()
mod.state = PackageState.APPROVED tool.state = PackageState.APPROVED
mod.name = "food" tool.name = "food"
mod.title = "Food" tool.title = "Food"
mod.license = licenses["LGPLv2.1"] tool.license = licenses["LGPLv2.1"]
mod.media_license = licenses["MIT"] tool.media_license = licenses["MIT"]
mod.type = PackageType.MOD tool.type = PackageType.TOOL
mod.author = admin_user tool.author = admin_user
mod.tags.append(tags["player_effects"]) tool.tags.append(tags["player_effects"])
mod.repo = "https://github.com/rubenwardy/food/" tool.repo = "https://github.com/rubenwardy/food/"
mod.issueTracker = "https://github.com/rubenwardy/food/issues/" tool.issueTracker = "https://github.com/rubenwardy/food/issues/"
mod.forums = 2960 tool.forums = 2960
mod.short_desc = "Adds lots of food and an API to manage ingredients" tool.short_desc = "Adds lots of food and an API to manage ingredients"
mod.desc = "This is the long desc" tool.desc = "This is the long desc"
session.add(mod) session.add(tool)
mod = Package() tool = Package()
mod.state = PackageState.APPROVED tool.state = PackageState.APPROVED
mod.name = "food_sweet" tool.name = "food_sweet"
mod.title = "Sweet Foods" tool.title = "Sweet Foods"
mod.license = licenses["CC0"] tool.license = licenses["CC0"]
mod.media_license = licenses["MIT"] tool.media_license = licenses["MIT"]
mod.type = PackageType.MOD tool.type = PackageType.TOOL
mod.author = admin_user tool.author = admin_user
mod.tags.append(tags["player_effects"]) tool.tags.append(tags["player_effects"])
mod.repo = "https://github.com/rubenwardy/food_sweet/" tool.repo = "https://github.com/rubenwardy/food_sweet/"
mod.issueTracker = "https://github.com/rubenwardy/food_sweet/issues/" tool.issueTracker = "https://github.com/rubenwardy/food_sweet/issues/"
mod.forums = 9039 tool.forums = 9039
mod.short_desc = "Adds sweet food" tool.short_desc = "Adds sweet food"
mod.desc = "This is the long desc" tool.desc = "This is the long desc"
food_sweet = mod food_sweet = tool
session.add(mod) session.add(tool)
game1 = Package() game1 = Package()
game1.state = PackageState.APPROVED game1.state = PackageState.APPROVED
@ -356,21 +356,21 @@ Uses the CTF PvP Engine.
session.add(rel) session.add(rel)
mod = Package() tool = Package()
mod.state = PackageState.APPROVED tool.state = PackageState.APPROVED
mod.name = "pixelbox" tool.name = "pixelbox"
mod.title = "PixelBOX Reloaded" tool.title = "PixelBOX Reloaded"
mod.license = licenses["CC0"] tool.license = licenses["CC0"]
mod.media_license = licenses["MIT"] tool.media_license = licenses["MIT"]
mod.type = PackageType.TXP tool.type = PackageType.ASSETPACK
mod.author = admin_user tool.author = admin_user
mod.forums = 14132 tool.forums = 14132
mod.short_desc = "This is an update of the original PixelBOX texture pack by the brillant artist Gambit" tool.short_desc = "This is an update of the original PixelBOX texture pack by the brillant artist Gambit"
mod.desc = "This is the long desc" tool.desc = "This is the long desc"
session.add(mod) session.add(tool)
rel = PackageRelease() rel = PackageRelease()
rel.package = mod rel.package = tool
rel.title = "v1.0.0" rel.title = "v1.0.0"
rel.url = "http://mamadou3.free.fr/Minetest/PixelBOX.zip" rel.url = "http://mamadou3.free.fr/Minetest/PixelBOX.zip"
rel.approved = True rel.approved = True
@ -379,7 +379,7 @@ Uses the CTF PvP Engine.
session.commit() session.commit()
metas = {} metas = {}
for package in Package.query.filter_by(type=PackageType.MOD).all(): for package in Package.query.filter_by(type=PackageType.TOOL).all():
meta = None meta = None
try: try:
meta = metas[package.name] meta = metas[package.name]

View File

@ -74,7 +74,7 @@ Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/).
* PUT `/api/packages/<author>/<name>/` (Update) * PUT `/api/packages/<author>/<name>/` (Update)
* Requires authentication. * Requires authentication.
* JSON dictionary with any of these keys (all are optional, null to delete Nullables): * JSON dictionary with any of these keys (all are optional, null to delete Nullables):
* `type`: One of `GAME`, `MOD`, `TXP`. * `type`: One of `GAME`, `TOOL`, `ASSETPACK`.
* `title`: Human-readable title. * `title`: Human-readable title.
* `name`: Technical name (needs permission if already approved). * `name`: Technical name (needs permission if already approved).
* `short_description` * `short_description`
@ -99,10 +99,10 @@ Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/).
* Supports [Package Queries](#package-queries) * Supports [Package Queries](#package-queries)
* [Paginated result](#paginated-results), max 300 results per page * [Paginated result](#paginated-results), max 300 results per page
* Each item in `items` will be a dictionary with the following keys: * Each item in `items` will be a dictionary with the following keys:
* `type`: One of `GAME`, `MOD`, `TXP`. * `type`: One of `GAME`, `TOOL`, `ASSETPACK`.
* `author`: Username of the package author. * `author`: Username of the package author.
* `name`: Package name. * `name`: Package name.
* `provides`: List of technical mod names inside the package. * `provides`: List of technical tool names inside the package.
* `depends`: List of hard dependencies. * `depends`: List of hard dependencies.
* Each dep will either be a metapackage dependency (`name`), or a * Each dep will either be a metapackage dependency (`name`), or a
package dependency (`author/name`). package dependency (`author/name`).
@ -134,11 +134,11 @@ curl -X PUT https://content.minetest.net/api/packages/username/name/ \
Example: Example:
/api/packages/?type=mod&type=game&q=mobs+fun&hide=nonfree&hide=gore /api/packages/?type=tool&type=game&q=mobs+fun&hide=nonfree&hide=gore
Supported query parameters: Supported query parameters:
* `type`: Package types (`mod`, `game`, `txp`). * `type`: Package types (`tool`, `game`, `asset_pack`).
* `q`: Query string. * `q`: Query string.
* `author`: Filter by author. * `author`: Filter by author.
* `tag`: Filter by tags. * `tag`: Filter by tags.
@ -173,7 +173,7 @@ Supported query parameters:
* `package` * `package`
* `author`: author username * `author`: author username
* `name`: technical name * `name`: technical name
* `type`: `mod`, `game`, or `txp` * `type`: `tool`, `game`, or `asset_pack`
* GET `/api/packages/<username>/<name>/releases/` (List) * GET `/api/packages/<username>/<name>/releases/` (List)
* Returns array of release dictionaries, see above, but without package info. * Returns array of release dictionaries, see above, but without package info.
* GET `/api/packages/<username>/<name>/releases/<id>/` (Read) * GET `/api/packages/<username>/<name>/releases/<id>/` (Read)
@ -304,7 +304,7 @@ Example:
```json ```json
[ [
{ {
"comment": "This is a really good mod!", "comment": "This is a really good tool!",
"created_at": "2021-11-24T16:18:33.764084", "created_at": "2021-11-24T16:18:33.764084",
"is_positive": true, "is_positive": true,
"title": "Really good", "title": "Really good",
@ -330,12 +330,12 @@ Example:
Example: Example:
/api/topics/?q=mobs&type=mod&type=game /api/topics/?q=mobs&type=tool&type=game
Supported query parameters: Supported query parameters:
* `q`: Query string. * `q`: Query string.
* `type`: Package types (`mod`, `game`, `txp`). * `type`: Package types (`tool`, `game`, `asset_pack`).
* `sort`: Sort by (`name`, `views`, `created_at`). * `sort`: Sort by (`name`, `views`, `created_at`).
* `show_added`: Show topics that have an existing package. * `show_added`: Show topics that have an existing package.
* `show_discarded`: Show topics marked as discarded. * `show_discarded`: Show topics marked as discarded.

View File

@ -69,8 +69,8 @@ is available.
* MUST: `screenshot.png` is present and up-to-date, with a correct aspect ratio (3:2, at least 300x200). * MUST: `screenshot.png` is present and up-to-date, with a correct aspect ratio (3:2, at least 300x200).
* MUST: Have a high resolution cover image on ContentDB (at least 1280x720 pixels). * MUST: Have a high resolution cover image on ContentDB (at least 1280x720 pixels).
It may be shown cropped to 16:9 aspect ratio, or shorter. It may be shown cropped to 16:9 aspect ratio, or shorter.
* MUST: mod.conf/game.conf/texture_pack.conf present with: * MUST: tool.conf/game.conf/texture_pack.conf present with:
* name (if mod or game) * name (if tool or game)
* description * description
* dependencies (if relevant) * dependencies (if relevant)
* `min_minetest_version` and `max_minetest_version` (if relevant) * `min_minetest_version` and `max_minetest_version` (if relevant)

View File

@ -14,7 +14,7 @@ and they will be subject to limited promotion.
of packages with non-free licenses.** of packages with non-free licenses.**
Minetest is free and open source software, and is only as big as it is now Minetest is free and open source software, and is only as big as it is now
because of this. It's pretty amazing you can take nearly any published mod and modify it because of this. It's pretty amazing you can take nearly any published tool and modify it
to how you like - add some features, maybe fix some bugs - and then share those to how you like - add some features, maybe fix some bugs - and then share those
modifications without the worry of legal issues. The project, itself, relies on open modifications without the worry of legal issues. The project, itself, relies on open
source contributions to survive - if it were non-free, then it would have died source contributions to survive - if it were non-free, then it would have died

View File

@ -14,8 +14,8 @@ Every type of content can have a `.conf` file that contains the metadata.
The filename of the `.conf` file depends on the content type: The filename of the `.conf` file depends on the content type:
* `mod.conf` for mods. * `tool.conf` for mods.
* `modpack.conf` for mod packs. * `modpack.conf` for tool packs.
* `game.conf` for games. * `game.conf` for games.
* `texture_pack.conf` for texture packs. * `texture_pack.conf` for texture packs.
@ -36,7 +36,7 @@ ContentDB understands the following information:
and for mods only: and for mods only:
* `name` - the mod technical name. * `name` - the tool technical name.
## .cdb.json ## .cdb.json
@ -46,7 +46,7 @@ to update the package meta.
It should be a JSON dictionary with one or more of the following optional keys: It should be a JSON dictionary with one or more of the following optional keys:
* `type`: One of `GAME`, `MOD`, `TXP`. * `type`: One of `GAME`, `TOOL`, `ASSETPACK`.
* `title`: Human-readable title. * `title`: Human-readable title.
* `name`: Technical name (needs permission if already approved). * `name`: Technical name (needs permission if already approved).
* `short_description` * `short_description`

View File

@ -8,7 +8,7 @@ the listings and to combat abuse.
* **No inappropriate content.** <sup>2.1</sup> * **No inappropriate content.** <sup>2.1</sup>
* **Content must be playable/useful, but not necessarily finished.** <sup>2.2</sup> * **Content must be playable/useful, but not necessarily finished.** <sup>2.2</sup>
* **Don't use the name of another mod unless your mod is a fork or reimplementation.** <sup>3</sup> * **Don't use the name of another tool unless your tool is a fork or reimplementation.** <sup>3</sup>
* **Licenses must allow derivatives, redistribution, and must not discriminate.** <sup>4</sup> * **Licenses must allow derivatives, redistribution, and must not discriminate.** <sup>4</sup>
* **Don't put promotions or advertisements in any package metadata.** <sup>5</sup> * **Don't put promotions or advertisements in any package metadata.** <sup>5</sup>
* **The ContentDB admin reserves the right to remove packages for any reason**, * **The ContentDB admin reserves the right to remove packages for any reason**,
@ -51,14 +51,14 @@ as this will help advise players.
Adding non-player facing mods, such as libraries and server tools, is perfectly fine Adding non-player facing mods, such as libraries and server tools, is perfectly fine
and encouraged. ContentDB isn't just for player-facing things, and adding and encouraged. ContentDB isn't just for player-facing things, and adding
libraries allows them to be installed when a mod depends on it. libraries allows them to be installed when a tool depends on it.
## 3. Technical Names ## 3. Technical Names
### 3.1 Right to a name ### 3.1 Right to a name
A package uses a name when it has that name or contains a mod that uses that name. A package uses a name when it has that name or contains a tool that uses that name.
The first package to use a name based on the creation of its forum topic or The first package to use a name based on the creation of its forum topic or
ContentDB submission has the right to the technical name. The use of a package ContentDB submission has the right to the technical name. The use of a package
@ -74,14 +74,14 @@ to change the name of the package, or your package won't be accepted.
We reserve the right to issue exceptions for this where we feel necessary. We reserve the right to issue exceptions for this where we feel necessary.
### 3.2. Mod Forks and Reimplementations ### 3.2. Tool Forks and Reimplementations
An exception to the above is that mods are allowed to have the same name as a An exception to the above is that mods are allowed to have the same name as a
mod if it's a fork of that mod (or a close reimplementation). In real terms, it tool if it's a fork of that tool (or a close reimplementation). In real terms, it
should be possible to use the new mod as a drop-in replacement. should be possible to use the new tool as a drop-in replacement.
We reserve the right to decide whether a mod counts as a fork or We reserve the right to decide whether a tool counts as a fork or
reimplementation of the mod that owns the name. reimplementation of the tool that owns the name.
## 4. Licenses ## 4. Licenses

View File

@ -83,9 +83,9 @@ Please [raise a report](https://content.minetest.net/report/?anon=0) if you
wish to remove your personal information. wish to remove your personal information.
ContentDB keeps a record of each username and forum topic on the forums, ContentDB keeps a record of each username and forum topic on the forums,
for use in indexing mod/game topics. ContentDB also requires the use of a username for use in indexing tool/game topics. ContentDB also requires the use of a username
to uniquely identify a package. Therefore, an author cannot be removed completely to uniquely identify a package. Therefore, an author cannot be removed completely
from ContentDB if they have any packages or mod/game topics on the forum. from ContentDB if they have any packages or tool/game topics on the forum.
If we are unable to remove your account for one of the above reasons, your user If we are unable to remove your account for one of the above reasons, your user
account will instead be wiped and deactivated, ending up exactly like an author account will instead be wiped and deactivated, ending up exactly like an author

View File

@ -140,8 +140,8 @@ class GameSupportResolver:
self.checked_packages.add(key) self.checked_packages.add(key)
if package.type != PackageType.MOD: if package.type != PackageType.TOOL:
raise LogicError(500, "Got non-mod") raise LogicError(500, "Got non-tool")
retval = PackageSet() retval = PackageSet()
@ -160,7 +160,7 @@ class GameSupportResolver:
return retval return retval
def update_all(self) -> None: def update_all(self) -> None:
for package in Package.query.filter(Package.type == PackageType.MOD, Package.state != PackageState.DELETED).all(): for package in Package.query.filter(Package.type == PackageType.TOOL, Package.state != PackageState.DELETED).all():
retval = self.resolve(package, []) retval = self.resolve(package, [])
for game in retval: for game in retval:
support = PackageGameSupport(package, game) support = PackageGameSupport(package, game)

View File

@ -140,10 +140,10 @@ def do_edit_package(user: User, package: Package, was_new: bool, was_web: bool,
if key in data: if key in data:
setattr(package, key, data[key]) setattr(package, key, data[key])
if package.type == PackageType.TXP: if package.type == PackageType.ASSETPACK:
package.license = package.media_license package.license = package.media_license
if was_new and package.type == PackageType.MOD: if was_new and package.type == PackageType.TOOL:
m = MetaPackage.GetOrCreate(package.name, {}) m = MetaPackage.GetOrCreate(package.name, {})
package.provides.append(m) package.provides.append(m)

View File

@ -49,9 +49,9 @@ class License(db.Model):
class PackageType(enum.Enum): class PackageType(enum.Enum):
MOD = "Mod" TOOL = "Tool"
GAME = "Game" GAME = "Game"
TXP = "Texture Pack" ASSETPACK = "Asset Pack"
def toName(self): def toName(self):
return self.name.lower() return self.name.lower()
@ -61,20 +61,20 @@ class PackageType(enum.Enum):
@property @property
def text(self): def text(self):
if self == PackageType.MOD: if self == PackageType.TOOL:
return lazy_gettext("Mod") return lazy_gettext("Tool")
elif self == PackageType.GAME: elif self == PackageType.GAME:
return lazy_gettext("Game") return lazy_gettext("Game")
elif self == PackageType.TXP: elif self == PackageType.ASSETPACK:
return lazy_gettext("Texture Pack") return lazy_gettext("Asset Pack")
@property @property
def plural(self): def plural(self):
if self == PackageType.MOD: if self == PackageType.TOOL:
return lazy_gettext("Mods") return lazy_gettext("Mods")
elif self == PackageType.GAME: elif self == PackageType.GAME:
return lazy_gettext("Games") return lazy_gettext("Games")
elif self == PackageType.TXP: elif self == PackageType.ASSETPACK:
return lazy_gettext("Texture Packs") return lazy_gettext("Texture Packs")
@classmethod @classmethod
@ -728,7 +728,7 @@ class Package(db.Model):
return False return False
needsScreenshot = \ needsScreenshot = \
(self.type == self.type.GAME or self.type == self.type.TXP) and \ (self.type == self.type.GAME or self.type == self.type.ASSETPACK) and \
self.screenshots.count() == 0 self.screenshots.count() == 0
return self.releases.filter(PackageRelease.task_id.is_(None)).count() > 0 and not needsScreenshot return self.releases.filter(PackageRelease.task_id.is_(None)).count() > 0 and not needsScreenshot

File diff suppressed because one or more lines are too long

View File

@ -53,7 +53,7 @@ ni:" ac co com edu gob mil net nom org ",np:" com edu gov mil net org ",nr:" biz
ps:" com edu gov net org plo sec ",pw:" belau co ed go ne or ",ro:" arts com firm info nom nt org rec store tm www ",rs:" ac co edu gov in org ",sb:" com edu gov net org ",sc:" com edu gov net org ",sh:" co com edu gov net nom org ",sl:" com edu gov net org ",st:" co com consulado edu embaixada gov mil net org principe saotome store ",sv:" com edu gob org red ",sz:" ac co org ",tr:" av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ",tt:" aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ", ps:" com edu gov net org plo sec ",pw:" belau co ed go ne or ",ro:" arts com firm info nom nt org rec store tm www ",rs:" ac co edu gov in org ",sb:" com edu gov net org ",sc:" com edu gov net org ",sh:" co com edu gov net nom org ",sl:" com edu gov net org ",st:" co com consulado edu embaixada gov mil net org principe saotome store ",sv:" com edu gob org red ",sz:" ac co org ",tr:" av bbs bel biz com dr edu gen gov info k12 name net org pol tel tsk tv web ",tt:" aero biz cat co com coop edu gov info int jobs mil mobi museum name net org pro tel travel ",
tw:" club com ebiz edu game gov idv mil net org ",mu:" ac co com gov net or org ",mz:" ac co edu gov org ",na:" co com ",nz:" ac co cri geek gen govt health iwi maori mil net org parliament school ",pa:" abo ac com edu gob ing med net nom org sld ",pt:" com edu gov int net nome org publ ",py:" com edu gov mil net org ",qa:" com edu gov mil net org ",re:" asso com nom ",ru:" ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ", tw:" club com ebiz edu game gov idv mil net org ",mu:" ac co com gov net or org ",mz:" ac co edu gov org ",na:" co com ",nz:" ac co cri geek gen govt health iwi maori mil net org parliament school ",pa:" abo ac com edu gob ing med net nom org sld ",pt:" com edu gov int net nome org publ ",py:" com edu gov mil net org ",qa:" com edu gov mil net org ",re:" asso com nom ",ru:" ac adygeya altai amur arkhangelsk astrakhan bashkiria belgorod bir bryansk buryatia cbg chel chelyabinsk chita chukotka chuvashia com dagestan e-burg edu gov grozny int irkutsk ivanovo izhevsk jar joshkar-ola kalmykia kaluga kamchatka karelia kazan kchr kemerovo khabarovsk khakassia khv kirov koenig komi kostroma kranoyarsk kuban kurgan kursk lipetsk magadan mari mari-el marine mil mordovia mosreg msk murmansk nalchik net nnov nov novosibirsk nsk omsk orenburg org oryol penza perm pp pskov ptz rnd ryazan sakhalin samara saratov simbirsk smolensk spb stavropol stv surgut tambov tatarstan tom tomsk tsaritsyn tsk tula tuva tver tyumen udm udmurtia ulan-ude vladikavkaz vladimir vladivostok volgograd vologda voronezh vrn vyatka yakutia yamal yekaterinburg yuzhno-sakhalinsk ",
rw:" ac co com edu gouv gov int mil net ",sa:" com edu gov med net org pub sch ",sd:" com edu gov info med net org tv ",se:" a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ",sg:" com edu gov idn net org per ",sn:" art com edu gouv org perso univ ",sy:" com edu gov mil net news org ",th:" ac co go in mi net or ",tj:" ac biz co com edu go gov info int mil name net nic org test web ",tn:" agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ", rw:" ac co com edu gouv gov int mil net ",sa:" com edu gov med net org pub sch ",sd:" com edu gov info med net org tv ",se:" a ac b bd c d e f g h i k l m n o org p parti pp press r s t tm u w x y z ",sg:" com edu gov idn net org per ",sn:" art com edu gouv org perso univ ",sy:" com edu gov mil net news org ",th:" ac co go in mi net or ",tj:" ac biz co com edu go gov info int mil name net nic org test web ",tn:" agrinet com defense edunet ens fin gov ind info intl mincom nat net org perso rnrt rns rnu tourism ",
tz:" ac co go ne or ",ua:" biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ",ug:" ac co go ne or org sc ",uk:" ac bl british-library co cym gov govt icnet jet lea ltd me mil mod national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ", tz:" ac co go ne or ",ua:" biz cherkassy chernigov chernovtsy ck cn co com crimea cv dn dnepropetrovsk donetsk dp edu gov if in ivano-frankivsk kh kharkov kherson khmelnitskiy kiev kirovograd km kr ks kv lg lugansk lutsk lviv me mk net nikolaev od odessa org pl poltava pp rovno rv sebastopol sumy te ternopil uzhgorod vinnica vn zaporizhzhe zhitomir zp zt ",ug:" ac co go ne or org sc ",uk:" ac bl british-library co cym gov govt icnet jet lea ltd me mil tool national-library-scotland nel net nhs nic nls org orgn parliament plc police sch scot soc ",
us:" dni fed isa kids nsn ",uy:" com edu gub mil net org ",ve:" co com edu gob info mil net org web ",vi:" co com k12 net org ",vn:" ac biz com edu gov health info int name net org pro ",ye:" co com gov ltd me net org plc ",yu:" ac co edu gov org ",za:" ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ",zm:" ac co com edu gov net org sch ",com:"ar br cn de eu gb gr hu jpn kr no qc ru sa se uk us uy za ",net:"gb jp se uk ", us:" dni fed isa kids nsn ",uy:" com edu gub mil net org ",ve:" co com edu gob info mil net org web ",vi:" co com k12 net org ",vn:" ac biz com edu gov health info int name net org pro ",ye:" co com gov ltd me net org plc ",yu:" ac co edu gov org ",za:" ac agric alt bourse city co cybernet db edu gov grondar iaccess imt inca landesign law mil net ngo nis nom olivetti org pix school tm web ",zm:" ac co com edu gov net org sch ",com:"ar br cn de eu gb gr hu jpn kr no qc ru sa se uk us uy za ",net:"gb jp se uk ",
org:"ae",de:"com "},has:function(k){var d=k.lastIndexOf(".");if(0>=d||d>=k.length-1)return!1;var m=k.lastIndexOf(".",d-1);if(0>=m||m>=d-1)return!1;var x=n.list[k.slice(d+1)];return x?0<=x.indexOf(" "+k.slice(m+1,d)+" "):!1},is:function(k){var d=k.lastIndexOf(".");if(0>=d||d>=k.length-1||0<=k.lastIndexOf(".",d-1))return!1;var m=n.list[k.slice(d+1)];return m?0<=m.indexOf(" "+k.slice(0,d)+" "):!1},get:function(k){var d=k.lastIndexOf(".");if(0>=d||d>=k.length-1)return null;var m=k.lastIndexOf(".",d-1); org:"ae",de:"com "},has:function(k){var d=k.lastIndexOf(".");if(0>=d||d>=k.length-1)return!1;var m=k.lastIndexOf(".",d-1);if(0>=m||m>=d-1)return!1;var x=n.list[k.slice(d+1)];return x?0<=x.indexOf(" "+k.slice(m+1,d)+" "):!1},is:function(k){var d=k.lastIndexOf(".");if(0>=d||d>=k.length-1||0<=k.lastIndexOf(".",d-1))return!1;var m=n.list[k.slice(d+1)];return m?0<=m.indexOf(" "+k.slice(0,d)+" "):!1},get:function(k){var d=k.lastIndexOf(".");if(0>=d||d>=k.length-1)return null;var m=k.lastIndexOf(".",d-1);
if(0>=m||m>=d-1)return null;var x=n.list[k.slice(d+1)];return!x||0>x.indexOf(" "+k.slice(m+1,d)+" ")?null:k.slice(m+1)},noConflict:function(){t.SecondLevelDomains===this&&(t.SecondLevelDomains=w);return this}};return n}); if(0>=m||m>=d-1)return null;var x=n.list[k.slice(d+1)];return!x||0>x.indexOf(" "+k.slice(m+1,d)+" ")?null:k.slice(m+1)},noConflict:function(){t.SecondLevelDomains===this&&(t.SecondLevelDomains=w);return this}};return n});

View File

@ -4,6 +4,6 @@
<LongName>ContentDB</LongName> <LongName>ContentDB</LongName>
<InputEncoding>UTF-8</InputEncoding> <InputEncoding>UTF-8</InputEncoding>
<Description>Search mods, games, and textures for Minetest.</Description> <Description>Search mods, games, and textures for Minetest.</Description>
<Tags>Minetest Mod Game Subgame Search</Tags> <Tags>Minetest Tool Game Subgame Search</Tags>
<Url type="text/html" method="get" template="https://content.minetest.net/packages?q={searchTerms}"/> <Url type="text/html" method="get" template="https://content.minetest.net/packages?q={searchTerms}"/>
</OpenSearchDescription> </OpenSearchDescription>

View File

@ -38,7 +38,7 @@ $(function() {
} }
let hint_mtmods = `Tip: let hint_mtmods = `Tip:
Don't include <i>Minetest</i>, <i>mod</i>, or <i>modpack</i> anywhere in the short description. Don't include <i>Minetest</i>, <i>tool</i>, or <i>modpack</i> anywhere in the short description.
It is unnecessary and wastes characters.`; It is unnecessary and wastes characters.`;
let hint_thegame = `Tip: let hint_thegame = `Tip:
@ -47,8 +47,8 @@ $(function() {
$("#short_desc").on("change paste keyup", function() { $("#short_desc").on("change paste keyup", function() {
const val = $(this).val().toLowerCase(); const val = $(this).val().toLowerCase();
if (val.indexOf("minetest") >= 0 || val.indexOf("mod") >= 0 || if (val.indexOf("minetest") >= 0 || val.indexOf("tool") >= 0 ||
val.indexOf("modpack") >= 0 || val.indexOf("mod pack") >= 0) { val.indexOf("modpack") >= 0 || val.indexOf("tool pack") >= 0) {
showHint($(this), hint_mtmods); showHint($(this), hint_mtmods);
} else if (val.indexOf("the game") >= 0) { } else if (val.indexOf("the game") >= 0) {
showHint($(this), hint_thegame); showHint($(this), hint_thegame);

View File

@ -80,7 +80,7 @@ def checkAllForumAccounts(forceNoSave=False):
regex_tag = re.compile(r"\[([a-z0-9_]+)\]") regex_tag = re.compile(r"\[([a-z0-9_]+)\]")
BANNED_NAMES = ["mod", "game", "old", "outdated", "wip", "api", "beta", "alpha", "git"] BANNED_NAMES = ["tool", "game", "old", "outdated", "wip", "api", "beta", "alpha", "git"]
def getNameFromTaglist(taglist): def getNameFromTaglist(taglist):
for tag in reversed(regex_tag.findall(taglist)): for tag in reversed(regex_tag.findall(taglist)):
if len(tag) < 30 and not tag in BANNED_NAMES and \ if len(tag) < 30 and not tag in BANNED_NAMES and \
@ -112,7 +112,7 @@ def getLinksFromModSearch():
pass pass
except urllib.error.URLError: except urllib.error.URLError:
print("Unable to open krocks mod search!") print("Unable to open krocks tool search!")
return links return links
return links return links
@ -122,8 +122,8 @@ def importTopicList():
links_by_id = getLinksFromModSearch() links_by_id = getLinksFromModSearch()
info_by_id = {} info_by_id = {}
getTopicsFromForum(11, out=info_by_id, extra={ 'type': PackageType.MOD, 'wip': False }) getTopicsFromForum(11, out=info_by_id, extra={ 'type': PackageType.TOOL, 'wip': False })
getTopicsFromForum(9, out=info_by_id, extra={ 'type': PackageType.MOD, 'wip': True }) getTopicsFromForum(9, out=info_by_id, extra={ 'type': PackageType.TOOL, 'wip': True })
getTopicsFromForum(15, out=info_by_id, extra={ 'type': PackageType.GAME, 'wip': False }) getTopicsFromForum(15, out=info_by_id, extra={ 'type': PackageType.GAME, 'wip': False })
getTopicsFromForum(50, out=info_by_id, extra={ 'type': PackageType.GAME, 'wip': True }) getTopicsFromForum(50, out=info_by_id, extra={ 'type': PackageType.GAME, 'wip': True })

View File

@ -78,7 +78,7 @@ def postReleaseCheckUpdate(self, release: PackageRelease, path):
tree = build_tree(path, expected_type=ContentType[release.package.type.name], tree = build_tree(path, expected_type=ContentType[release.package.type.name],
author=release.package.author.username, name=release.package.name) author=release.package.author.username, name=release.package.name)
if tree.name is not None and release.package.name != tree.name and tree.type == ContentType.MOD: if tree.name is not None and release.package.name != tree.name and tree.type == ContentType.TOOL:
raise MinetestCheckError(f"Expected {tree.relative} to have technical name {release.package.name}, instead has name {tree.name}") raise MinetestCheckError(f"Expected {tree.relative} to have technical name {release.package.name}, instead has name {tree.name}")
cache = {} cache = {}
@ -99,9 +99,9 @@ def postReleaseCheckUpdate(self, release: PackageRelease, path):
optional_depends = tree.fold("meta", "optional_depends") optional_depends = tree.fold("meta", "optional_depends")
# Filter out provides # Filter out provides
for mod in provides: for tool in provides:
depends.discard(mod) depends.discard(tool)
optional_depends.discard(mod) optional_depends.discard(tool)
# Raise error on unresolved game dependencies # Raise error on unresolved game dependencies
if package.type == PackageType.GAME and len(depends) > 0: if package.type == PackageType.GAME and len(depends) > 0:
@ -116,7 +116,7 @@ def postReleaseCheckUpdate(self, release: PackageRelease, path):
db.session.add(Dependency(package, meta=meta, optional=True)) db.session.add(Dependency(package, meta=meta, optional=True))
# Update game supports # Update game supports
if package.type == PackageType.MOD: if package.type == PackageType.TOOL:
resolver = GameSupportResolver() resolver = GameSupportResolver()
resolver.update(package) resolver.update(package)

View File

@ -8,13 +8,13 @@ class MinetestCheckError(Exception):
class ContentType(Enum): class ContentType(Enum):
UNKNOWN = "unknown" UNKNOWN = "unknown"
MOD = "mod" TOOL = "tool"
MODPACK = "modpack" MODPACK = "modpack"
GAME = "game" GAME = "game"
TXP = "texture pack" ASSETPACK = "texture pack"
def isModLike(self): def isModLike(self):
return self == ContentType.MOD or self == ContentType.MODPACK return self == ContentType.TOOL or self == ContentType.MODPACK
def validate_same(self, other): def validate_same(self, other):
""" """
@ -22,12 +22,12 @@ class ContentType(Enum):
""" """
assert other assert other
if self == ContentType.MOD: if self == ContentType.TOOL:
if not other.isModLike(): if not other.isModLike():
raise MinetestCheckError("Expected a mod or modpack, found " + other.value) raise MinetestCheckError("Expected a tool or modpack, found " + other.value)
elif self == ContentType.TXP: elif self == ContentType.ASSETPACK:
if other != ContentType.UNKNOWN and other != ContentType.TXP: if other != ContentType.UNKNOWN and other != ContentType.ASSETPACK:
raise MinetestCheckError("expected a " + self.value + ", found a " + other.value) raise MinetestCheckError("expected a " + self.value + ", found a " + other.value)
elif other != self: elif other != self:

View File

@ -19,14 +19,14 @@ def detect_type(path):
if os.path.isfile(path + "/game.conf"): if os.path.isfile(path + "/game.conf"):
return ContentType.GAME return ContentType.GAME
elif os.path.isfile(path + "/init.lua"): elif os.path.isfile(path + "/init.lua"):
return ContentType.MOD return ContentType.TOOL
elif os.path.isfile(path + "/modpack.txt") or \ elif os.path.isfile(path + "/modpack.txt") or \
os.path.isfile(path + "/modpack.conf"): os.path.isfile(path + "/modpack.conf"):
return ContentType.MODPACK return ContentType.MODPACK
# elif os.path.isdir(path + "/mods"): # elif os.path.isdir(path + "/mods"):
# return ContentType.GAME # return ContentType.GAME
elif os.path.isfile(path + "/texture_pack.conf"): elif os.path.isfile(path + "/texture_pack.conf"):
return ContentType.TXP return ContentType.ASSETPACK
else: else:
return ContentType.UNKNOWN return ContentType.UNKNOWN
@ -56,9 +56,9 @@ class PackageTreeNode:
if not os.path.isdir(baseDir + "/mods"): if not os.path.isdir(baseDir + "/mods"):
raise MinetestCheckError("Game at {} does not have a mods/ folder".format(self.relative)) raise MinetestCheckError("Game at {} does not have a mods/ folder".format(self.relative))
self.add_children_from_mod_dir("mods") self.add_children_from_mod_dir("mods")
elif self.type == ContentType.MOD: elif self.type == ContentType.TOOL:
if self.name and not basenamePattern.match(self.name): if self.name and not basenamePattern.match(self.name):
raise MinetestCheckError("Invalid base name for mod {} at {}, names must only contain a-z0-9_." \ raise MinetestCheckError("Invalid base name for tool {} at {}, names must only contain a-z0-9_." \
.format(self.name, self.relative)) .format(self.name, self.relative))
elif self.type == ContentType.MODPACK: elif self.type == ContentType.MODPACK:
self.add_children_from_mod_dir(None) self.add_children_from_mod_dir(None)
@ -72,11 +72,11 @@ class PackageTreeNode:
def getMetaFileName(self): def getMetaFileName(self):
if self.type == ContentType.GAME: if self.type == ContentType.GAME:
return "game.conf" return "game.conf"
elif self.type == ContentType.MOD: elif self.type == ContentType.TOOL:
return "mod.conf" return "tool.conf"
elif self.type == ContentType.MODPACK: elif self.type == ContentType.MODPACK:
return "modpack.conf" return "modpack.conf"
elif self.type == ContentType.TXP: elif self.type == ContentType.ASSETPACK:
return "texture_pack.conf" return "texture_pack.conf"
else: else:
return None return None
@ -143,11 +143,11 @@ class PackageTreeNode:
for dep in deps: for dep in deps:
if not basenamePattern.match(dep): if not basenamePattern.match(dep):
if " " in dep: if " " in dep:
raise MinetestCheckError("Invalid dependency name '{}' for mod at {}, did you forget a comma?" \ raise MinetestCheckError("Invalid dependency name '{}' for tool at {}, did you forget a comma?" \
.format(dep, self.relative)) .format(dep, self.relative))
else: else:
raise MinetestCheckError( raise MinetestCheckError(
"Invalid dependency name '{}' for mod at {}, names must only contain a-z0-9_." \ "Invalid dependency name '{}' for tool at {}, names must only contain a-z0-9_." \
.format(dep, self.relative)) .format(dep, self.relative))
# Check dependencies # Check dependencies
@ -188,16 +188,16 @@ class PackageTreeNode:
if not entry.startswith('.') and os.path.isdir(path): if not entry.startswith('.') and os.path.isdir(path):
child = PackageTreeNode(path, relative + entry + "/", name=entry) child = PackageTreeNode(path, relative + entry + "/", name=entry)
if not child.type.isModLike(): if not child.type.isModLike():
raise MinetestCheckError("Expecting mod or modpack, found {} at {} inside {}" \ raise MinetestCheckError("Expecting tool or modpack, found {} at {} inside {}" \
.format(child.type.value, child.relative, self.type.value)) .format(child.type.value, child.relative, self.type.value))
if child.name is None: if child.name is None:
raise MinetestCheckError("Missing base name for mod at {}".format(self.relative)) raise MinetestCheckError("Missing base name for tool at {}".format(self.relative))
self.children.append(child) self.children.append(child)
def getModNames(self): def getModNames(self):
return self.fold("name", type=ContentType.MOD) return self.fold("name", type=ContentType.TOOL)
# attr: Attribute name # attr: Attribute name
# key: Key in attribute # key: Key in attribute

View File

@ -24,13 +24,13 @@
<div class="collapse navbar-collapse" id="navbarColor01"> <div class="collapse navbar-collapse" id="navbarColor01">
<ul class="navbar-nav mr-auto"> <ul class="navbar-nav mr-auto">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{{ url_for('packages.list_all', type='mod') }}">{{ _("Mods") }}</a> <a class="nav-link" href="{{ url_for('packages.list_all', type='tool') }}">{{ _("Mods") }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{{ url_for('packages.list_all', type='game') }}">{{ _("Games") }}</a> <a class="nav-link" href="{{ url_for('packages.list_all', type='game') }}">{{ _("Games") }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{{ url_for('packages.list_all', type='txp') }}">{{ _("Texture Packs") }}</a> <a class="nav-link" href="{{ url_for('packages.list_all', type='asset_pack') }}">{{ _("Texture Packs") }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{{ url_for('packages.list_all', random=1, lucky=1) }}">{{ _("Random") }}</a> <a class="nav-link" href="{{ url_for('packages.list_all', random=1, lucky=1) }}">{{ _("Random") }}</a>

View File

@ -118,14 +118,14 @@
{{ render_pkggrid(pop_gam) }} {{ render_pkggrid(pop_gam) }}
<a href="{{ url_for('packages.list_all', type='mod', sort='score', order='desc') }}" class="btn btn-secondary float-right"> <a href="{{ url_for('packages.list_all', type='tool', sort='score', order='desc') }}" class="btn btn-secondary float-right">
{{ _("See more") }} {{ _("See more") }}
</a> </a>
<h2 class="my-3">{{ _("Top Mods") }}</h2> <h2 class="my-3">{{ _("Top Mods") }}</h2>
{{ render_pkggrid(pop_mod) }} {{ render_pkggrid(pop_mod) }}
<a href="{{ url_for('packages.list_all', type='txp', sort='score', order='desc') }}" class="btn btn-secondary float-right"> <a href="{{ url_for('packages.list_all', type='asset_pack', sort='score', order='desc') }}" class="btn btn-secondary float-right">
{{ _("See more") }} {{ _("See more") }}
</a> </a>
<h2 class="my-3">{{ _("Top Texture Packs") }}</h2> <h2 class="my-3">{{ _("Top Texture Packs") }}</h2>

View File

@ -37,7 +37,7 @@
{% endif %} {% endif %}
{% endset %} {% endset %}
{% elif (package.type == package.type.GAME or package.type == package.type.TXP) and package.screenshots.count() == 0 %} {% elif (package.type == package.type.GAME or package.type == package.type.ASSETPACK) and package.screenshots.count() == 0 %}
{% set message = _("You need to add at least one screenshot.") %} {% set message = _("You need to add at least one screenshot.") %}
{% elif package.getMissingHardDependenciesQuery().count() > 0 %} {% elif package.getMissingHardDependenciesQuery().count() > 0 %}

View File

@ -20,11 +20,11 @@
{{ package.short_desc }} {{ package.short_desc }}
</p> </p>
{% if not package.license.is_foss and not package.media_license.is_foss and package.type != package.type.TXP %} {% if not package.license.is_foss and not package.media_license.is_foss and package.type != package.type.ASSETPACK %}
<p style="color:#f33;"> <p style="color:#f33;">
{{ _("<b>Warning:</b> Non-free code and media.") }} {{ _("<b>Warning:</b> Non-free code and media.") }}
</p> </p>
{% elif not package.license.is_foss and package.type != package.type.TXP %} {% elif not package.license.is_foss and package.type != package.type.ASSETPACK %}
<p style="color:#f33;"> <p style="color:#f33;">
{{ _("<b>Warning:</b> Non-free code.") }} {{ _("<b>Warning:</b> Non-free code.") }}
</p> </p>

View File

@ -15,7 +15,7 @@
{{ render_pkggrid(mpackage.packages.filter_by(type="GAME", state="APPROVED").all()) }} {{ render_pkggrid(mpackage.packages.filter_by(type="GAME", state="APPROVED").all()) }}
<h3>{{ _("Mods") }}</h3> <h3>{{ _("Mods") }}</h3>
{{ render_pkggrid(mpackage.packages.filter_by(type="MOD", state="APPROVED").all()) }} {{ render_pkggrid(mpackage.packages.filter_by(type="TOOL", state="APPROVED").all()) }}
{% if similar_topics %} {% if similar_topics %}
<h3>{{ _("Forum Topics") }}</h3> <h3>{{ _("Forum Topics") }}</h3>

View File

@ -41,7 +41,7 @@
{{ render_pkggrid(updated) }} {{ render_pkggrid(updated) }}
<a href="{{ url_for('packages.list_all', type='mod', sort='score', order='desc', game=package.getId()) }}" class="btn btn-secondary float-right"> <a href="{{ url_for('packages.list_all', type='tool', sort='score', order='desc', game=package.getId()) }}" class="btn btn-secondary float-right">
{{ _("See more") }} {{ _("See more") }}
</a> </a>
<h2 class="my-3">{{ _("Top Mods") }}</h2> <h2 class="my-3">{{ _("Top Mods") }}</h2>

View File

@ -50,11 +50,11 @@
{% endif %} {% endif %}
</a> </a>
{% if package.type == package.type.MOD %} {% if package.type == package.type.TOOL %}
{% set installing_url = "https://wiki.minetest.net/Installing_Mods" %} {% set installing_url = "https://wiki.minetest.net/Installing_Mods" %}
{% elif package.type == package.type.GAME %} {% elif package.type == package.type.GAME %}
{% set installing_url = "https://wiki.minetest.net/Games#Installing_games" %} {% set installing_url = "https://wiki.minetest.net/Games#Installing_games" %}
{% elif package.type == package.type.TXP %} {% elif package.type == package.type.ASSETPACK %}
{% set installing_url = "https://wiki.minetest.net/Installing_Texture_Packs" %} {% set installing_url = "https://wiki.minetest.net/Installing_Texture_Packs" %}
{% else %} {% else %}
{{ 0 / 0 }} {{ 0 / 0 }}
@ -76,9 +76,9 @@
{% endblock %} {% endblock %}
{% block container %} {% block container %}
{% if not package.license.is_foss and not package.media_license.is_foss and package.type != package.type.TXP %} {% if not package.license.is_foss and not package.media_license.is_foss and package.type != package.type.ASSETPACK %}
{% set package_warning=_("Non-free code and media") %} {% set package_warning=_("Non-free code and media") %}
{% elif not package.license.is_foss and package.type != package.type.TXP %} {% elif not package.license.is_foss and package.type != package.type.ASSETPACK %}
{% set package_warning=_("Non-free code") %} {% set package_warning=_("Non-free code") %}
{% elif not package.media_license.is_foss %} {% elif not package.media_license.is_foss %}
{% set package_warning=_("Non-free media") %} {% set package_warning=_("Non-free media") %}
@ -384,7 +384,7 @@
</a> </a>
{% endif %} {% endif %}
{% if package.type != package.type.TXP %} {% if package.type != package.type.ASSETPACK %}
<h3>{{ _("Dependencies") }}</h3> <h3>{{ _("Dependencies") }}</h3>
<dl> <dl>
<dt>{{ _("Required") }}</dt> <dt>{{ _("Required") }}</dt>
@ -432,7 +432,7 @@
</dl> </dl>
{% endif %} {% endif %}
{% if package.type == package.type.MOD %} {% if package.type == package.type.TOOL %}
<h3>{{ _("Compatible Games") }}</h3> <h3>{{ _("Compatible Games") }}</h3>
{% for support in package.getSortedSupportedGames() %} {% for support in package.getSortedSupportedGames() %}
<a class="badge badge-secondary" <a class="badge badge-secondary"
@ -462,7 +462,7 @@
<dd> <dd>
{% if package.license == package.media_license %} {% if package.license == package.media_license %}
{{ render_license(package.license) }} {{ render_license(package.license) }}
{% elif package.type == package.type.TXP %} {% elif package.type == package.type.ASSETPACK %}
{{ render_license(package.media_license) }} {{ render_license(package.media_license) }}
{% else %} {% else %}
{{ _("%(code_license)s for code,<br>%(media_license)s for media.", {{ _("%(code_license)s for code,<br>%(media_license)s for media.",

View File

@ -10,23 +10,23 @@ def make_package(name: str, versions: List[Tuple[Optional[str], Optional[str]]])
license = License.query.filter_by(name="MIT").first() license = License.query.filter_by(name="MIT").first()
author = User.query.first() author = User.query.first()
mod = Package() tool = Package()
mod.state = PackageState.APPROVED tool.state = PackageState.APPROVED
mod.name = name.lower() tool.name = name.lower()
mod.title = name tool.title = name
mod.license = license tool.license = license
mod.media_license = license tool.media_license = license
mod.type = PackageType.MOD tool.type = PackageType.TOOL
mod.author = author tool.author = author
mod.short_desc = "The content library should not be used yet as it is still in alpha" tool.short_desc = "The content library should not be used yet as it is still in alpha"
mod.desc = "This is the long desc" tool.desc = "This is the long desc"
db.session.add(mod) db.session.add(tool)
rels = [] rels = []
for (minv, maxv) in versions: for (minv, maxv) in versions:
rel = PackageRelease() rel = PackageRelease()
rel.package = mod rel.package = tool
rel.title = "test" rel.title = "test"
rel.url = "https://github.com/ezhh/handholds/archive/master.zip" rel.url = "https://github.com/ezhh/handholds/archive/master.zip"

View File

@ -13,7 +13,7 @@ The query arguments will include a list of supported types, the current
and any hidden [Content Flags](https://content.minetest.net/help/content_flags/). and any hidden [Content Flags](https://content.minetest.net/help/content_flags/).
Example URL: Example URL:
<https://content.minetest.net/api/packages/?type=mod&type=game&type=txp&protocol_version=39&engine_version=5.3.0&hide=nonfree&hide=desktop_default> <https://content.minetest.net/api/packages/?type=tool&type=game&type=asset_pack&protocol_version=39&engine_version=5.3.0&hide=nonfree&hide=desktop_default>
Example response: Example response:
@ -33,7 +33,7 @@ Example response:
`thumbnail` is optional, but all other fields are required. `thumbnail` is optional, but all other fields are required.
`type` is one of `mod`, `game`, or `txp`. `type` is one of `tool`, `game`, or `asset_pack`.
`release` is the release ID. Newer releases have higher IDs. `release` is the release ID. Newer releases have higher IDs.
Minetest compares this ID to a locally stored version to detect whether a package has updates. Minetest compares this ID to a locally stored version to detect whether a package has updates.
@ -67,7 +67,7 @@ dependencies for a package.
Then, it resolves each dependency recursively. Then, it resolves each dependency recursively.
Say you're resolving for `basic_materials`, then it will attempt to find the mod in this order: Say you're resolving for `basic_materials`, then it will attempt to find the tool in this order:
1. It first checks installed mods in the game and mods folder (ie: `mods/basic_materials/`) 1. It first checks installed mods in the game and mods folder (ie: `mods/basic_materials/`)
2. Then it looks on ContentDB for exact name matches (ie: `VanessaE/basic_materials`) 2. Then it looks on ContentDB for exact name matches (ie: `VanessaE/basic_materials`)
@ -77,7 +77,7 @@ Say you're resolving for `basic_materials`, then it will attempt to find the mod
### Long version ### Long version
When installing a package, an API request is made to ContentDB to find out the dependencies. When installing a package, an API request is made to ContentDB to find out the dependencies.
If there are no dependencies, then the mod is installed straight away. If there are no dependencies, then the tool is installed straight away.
If there are dependencies, it will resolve them and show a dialog with a list of mods to install. If there are dependencies, it will resolve them and show a dialog with a list of mods to install.

View File

@ -68,7 +68,7 @@ def upgrade():
sa.Column('title', sa.String(length=100), nullable=False), sa.Column('title', sa.String(length=100), nullable=False),
sa.Column('shortDesc', sa.String(length=200), nullable=False), sa.Column('shortDesc', sa.String(length=200), nullable=False),
sa.Column('desc', sa.Text(), nullable=True), sa.Column('desc', sa.Text(), nullable=True),
sa.Column('type', sa.Enum('MOD', 'GAME', 'TXP', name='packagetype'), nullable=True), sa.Column('type', sa.Enum('TOOL', 'GAME', 'ASSETPACK', name='packagetype'), nullable=True),
sa.Column('license_id', sa.Integer(), nullable=True), sa.Column('license_id', sa.Integer(), nullable=True),
sa.Column('approved', sa.Boolean(), nullable=False), sa.Column('approved', sa.Boolean(), nullable=False),
sa.Column('repo', sa.String(length=200), nullable=True), sa.Column('repo', sa.String(length=200), nullable=True),

View File

@ -16,7 +16,7 @@ branch_labels = None
depends_on = None depends_on = None
from sqlalchemy.dialects.postgresql import ENUM from sqlalchemy.dialects.postgresql import ENUM
type_enum = ENUM('MOD', 'GAME', 'TXP', name='packagetype', create_type=False) type_enum = ENUM('TOOL', 'GAME', 'ASSETPACK', name='packagetype', create_type=False)
def upgrade(): def upgrade():
type_enum.create(op.get_bind(), checkfirst=True) type_enum.create(op.get_bind(), checkfirst=True)

View File

@ -944,15 +944,15 @@ msgid "Uploaded image isn't actually an image"
msgstr "Hochgeladenes Bild ist nicht wirklich ein Bild" msgstr "Hochgeladenes Bild ist nicht wirklich ein Bild"
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "Mod" msgstr "Tool"
#: app/models/packages.py:67 #: app/models/packages.py:67
msgid "Game" msgid "Game"
msgstr "Spiel" msgstr "Spiel"
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "Texturenpaket" msgstr "Texturenpaket"
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -936,15 +936,15 @@ msgid "Uploaded image isn't actually an image"
msgstr "La imagen subida no es realmente una imagen" msgstr "La imagen subida no es realmente una imagen"
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "Mod" msgstr "Tool"
#: app/models/packages.py:67 #: app/models/packages.py:67
msgid "Game" msgid "Game"
msgstr "Juego" msgstr "Juego"
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "Paquete de texturas" msgstr "Paquete de texturas"
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27
@ -2394,7 +2394,7 @@ msgstr "Emblemas"
#: app/templates/packages/similar.html:4 #: app/templates/packages/similar.html:4
msgid "Modname Uniqueness" msgid "Modname Uniqueness"
msgstr "Originalidad del nombre del mod" msgstr "Originalidad del nombre del tool"
#: app/templates/packages/similar.html:12 #: app/templates/packages/similar.html:12
msgid "Packages sharing provided mods" msgid "Packages sharing provided mods"

View File

@ -940,15 +940,15 @@ msgid "Uploaded image isn't actually an image"
msgstr "L'image envoyée n'est pas une image" msgstr "L'image envoyée n'est pas une image"
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "Mod" msgstr "Tool"
#: app/models/packages.py:67 #: app/models/packages.py:67
msgid "Game" msgid "Game"
msgstr "Jeu" msgstr "Jeu"
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "Pack de texture" msgstr "Pack de texture"
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27
@ -2429,7 +2429,7 @@ msgstr "Badges"
#: app/templates/packages/similar.html:4 #: app/templates/packages/similar.html:4
msgid "Modname Uniqueness" msgid "Modname Uniqueness"
msgstr "Originalité du nom du mod" msgstr "Originalité du nom du tool"
#: app/templates/packages/similar.html:12 #: app/templates/packages/similar.html:12
msgid "Packages sharing provided mods" msgid "Packages sharing provided mods"

View File

@ -947,7 +947,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -956,7 +956,7 @@ msgid "Game"
msgstr "Név" msgstr "Név"
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "" msgstr ""
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -931,7 +931,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -941,12 +941,12 @@ msgstr "Nama"
#: app/models/packages.py:69 #: app/models/packages.py:69
#, fuzzy #, fuzzy
msgid "Texture Pack" msgid "Asset Pack"
msgstr "Paket Tekstur" msgstr "Paket Tekstur"
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27
msgid "Mods" msgid "Mods"
msgstr "Mod" msgstr "Tool"
#: app/models/packages.py:76 app/templates/base.html:30 #: app/models/packages.py:76 app/templates/base.html:30
msgid "Games" msgid "Games"
@ -1185,7 +1185,7 @@ msgstr "Permainan Teratas"
#: app/templates/index.html:124 #: app/templates/index.html:124
msgid "Top Mods" msgid "Top Mods"
msgstr "Mod Teratas" msgstr "Tool Teratas"
#: app/templates/index.html:131 #: app/templates/index.html:131
msgid "Top Texture Packs" msgid "Top Texture Packs"
@ -2408,15 +2408,15 @@ msgstr "Lencana"
#: app/templates/packages/similar.html:4 #: app/templates/packages/similar.html:4
msgid "Modname Uniqueness" msgid "Modname Uniqueness"
msgstr "Keunikan Nama Mod" msgstr "Keunikan Nama Tool"
#: app/templates/packages/similar.html:12 #: app/templates/packages/similar.html:12
msgid "Packages sharing provided mods" msgid "Packages sharing provided mods"
msgstr "Paket-paket yang turut memakai mod yang diberikan" msgstr "Paket-paket yang turut memakai tool yang diberikan"
#: app/templates/packages/similar.html:14 #: app/templates/packages/similar.html:14
msgid "This package contains modnames that are present in the following packages:" msgid "This package contains modnames that are present in the following packages:"
msgstr "Paket ini memiliki nama mod yang ada dalam paket-paket berikut:" msgstr "Paket ini memiliki nama tool yang ada dalam paket-paket berikut:"
#: app/templates/packages/similar.html:32 #: app/templates/packages/similar.html:32
msgid "Similar Forum Topics" msgid "Similar Forum Topics"

View File

@ -904,7 +904,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -912,7 +912,7 @@ msgid "Game"
msgstr "" msgstr ""
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "" msgstr ""
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -904,7 +904,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -912,7 +912,7 @@ msgid "Game"
msgstr "" msgstr ""
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "" msgstr ""
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -940,7 +940,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "Imej yang dimuat naik sebenarnya bukan sejenis imej" msgstr "Imej yang dimuat naik sebenarnya bukan sejenis imej"
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "Mods" msgstr "Mods"
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -948,7 +948,7 @@ msgid "Game"
msgstr "Permainan" msgstr "Permainan"
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "Pek Tekstur" msgstr "Pek Tekstur"
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -906,7 +906,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -915,7 +915,7 @@ msgid "Game"
msgstr "Navn" msgstr "Navn"
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "" msgstr ""
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -933,7 +933,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "Загруженное изображение на самом деле не является изображением" msgstr "Загруженное изображение на самом деле не является изображением"
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "Мод" msgstr "Мод"
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -941,7 +941,7 @@ msgid "Game"
msgstr "Игра" msgstr "Игра"
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "Пакет текстур" msgstr "Пакет текстур"
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -906,7 +906,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -914,7 +914,7 @@ msgid "Game"
msgstr "" msgstr ""
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "" msgstr ""
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -910,7 +910,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -918,7 +918,7 @@ msgid "Game"
msgstr "" msgstr ""
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "" msgstr ""
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -911,8 +911,8 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "Mod" msgstr "Tool"
#: app/models/packages.py:67 #: app/models/packages.py:67
#, fuzzy #, fuzzy
@ -921,7 +921,7 @@ msgstr "子游戏"
#: app/models/packages.py:69 #: app/models/packages.py:69
#, fuzzy #, fuzzy
msgid "Texture Pack" msgid "Asset Pack"
msgstr "材质包" msgstr "材质包"
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27

View File

@ -909,7 +909,7 @@ msgid "Uploaded image isn't actually an image"
msgstr "" msgstr ""
#: app/models/packages.py:65 #: app/models/packages.py:65
msgid "Mod" msgid "Tool"
msgstr "" msgstr ""
#: app/models/packages.py:67 #: app/models/packages.py:67
@ -917,7 +917,7 @@ msgid "Game"
msgstr "" msgstr ""
#: app/models/packages.py:69 #: app/models/packages.py:69
msgid "Texture Pack" msgid "Asset Pack"
msgstr "" msgstr ""
#: app/models/packages.py:74 app/templates/base.html:27 #: app/models/packages.py:74 app/templates/base.html:27